169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Redistribution and use in source and binary forms, with or without
369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// modification, are permitted provided that the following conditions are
469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// met:
569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//
669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//     * Redistributions of source code must retain the above copyright
769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       notice, this list of conditions and the following disclaimer.
869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//     * Redistributions in binary form must reproduce the above
969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       copyright notice, this list of conditions and the following
1069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       disclaimer in the documentation and/or other materials provided
1169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       with the distribution.
1269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//     * Neither the name of Google Inc. nor the names of its
1369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       contributors may be used to endorse or promote products derived
1469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       from this software without specific prior written permission.
1569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//
1669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <utility>
2969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/global-handles.h"
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/snapshot.h"
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h"
3569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
3669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochusing namespace v8::internal;
3769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
3869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Isolate* GetIsolateFrom(LocalContext* context) {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return reinterpret_cast<Isolate*>((*context)->GetIsolate());
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Handle<JSWeakMap> AllocateJSWeakMap(Isolate* isolate) {
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate->factory();
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map = factory->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSObject> weakmap_obj = factory->NewJSObjectFromMap(map);
4869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<JSWeakMap> weakmap(JSWeakMap::cast(*weakmap_obj));
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do not leak handles for the hash table, it would make entries strong.
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(isolate);
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 1);
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    weakmap->set_table(*table);
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return weakmap;
5669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
5769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
5869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic void PutIntoWeakMap(Handle<JSWeakMap> weakmap,
5969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                           Handle<JSObject> key,
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Handle<Object> value) {
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<ObjectHashTable> table = ObjectHashTable::Put(
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<ObjectHashTable>(ObjectHashTable::cast(weakmap->table())),
6369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Handle<JSObject>(JSObject::cast(*key)),
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      value);
6569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  weakmap->set_table(*table);
6669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
6769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
6869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic int NumberOfWeakCalls = 0;
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void WeakPointerCallback(
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::WeakCallbackData<v8::Value, void>& data) {
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  std::pair<v8::Persistent<v8::Value>*, int>* p =
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<std::pair<v8::Persistent<v8::Value>*, int>*>(
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          data.GetParameter());
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(1234, p->second);
7569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  NumberOfWeakCalls++;
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  p->first->Reset();
7769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
7869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
7969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
8069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTEST(Weakness) {
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FLAG_incremental_marking = false;
8269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext context;
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = GetIsolateFrom(&context);
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate->factory();
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap = isolate->heap();
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSWeakMap> weakmap = AllocateJSWeakMap(isolate);
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GlobalHandles* global_handles = isolate->global_handles();
8969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
9069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Keep global reference to the key.
9169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<Object> key;
9269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  {
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(isolate);
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<JSObject> object = factory->NewJSObjectFromMap(map);
9669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    key = global_handles->Create(*object);
9769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
9869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(!global_handles->IsWeak(key.location()));
9969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
10069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Put entry into weak map.
10169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  {
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(isolate);
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PutIntoWeakMap(weakmap,
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Handle<JSObject>(JSObject::cast(*key)),
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Handle<Smi>(Smi::FromInt(23), isolate));
10669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(1, ObjectHashTable::cast(weakmap->table())->NumberOfElements());
10869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
10969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Force a full GC.
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(false);
11169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, NumberOfWeakCalls);
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(1, ObjectHashTable::cast(weakmap->table())->NumberOfElements());
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      0, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements());
11569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Make the global reference to the key weak.
11769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  {
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(isolate);
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    std::pair<Handle<Object>*, int> handle_and_id(&key, 1234);
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GlobalHandles::MakeWeak(key.location(),
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            reinterpret_cast<void*>(&handle_and_id),
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            &WeakPointerCallback);
12369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
12469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(global_handles->IsWeak(key.location()));
12569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
12669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Force a full GC.
12769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Perform two consecutive GCs because the first one will only clear
12869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // weak references whereas the second one will also clear weak maps.
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(false);
13069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(1, NumberOfWeakCalls);
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(1, ObjectHashTable::cast(weakmap->table())->NumberOfElements());
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      0, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements());
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(false);
13569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(1, NumberOfWeakCalls);
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0, ObjectHashTable::cast(weakmap->table())->NumberOfElements());
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      1, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements());
13969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
14069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
14169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
14269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTEST(Shrinking) {
14369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext context;
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = GetIsolateFrom(&context);
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate->factory();
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap = isolate->heap();
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSWeakMap> weakmap = AllocateJSWeakMap(isolate);
14969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
15069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Check initial capacity.
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(32, ObjectHashTable::cast(weakmap->table())->Capacity());
15269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
15369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Fill up weak map to trigger capacity change.
15469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  {
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(isolate);
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
15769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    for (int i = 0; i < 32; i++) {
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<JSObject> object = factory->NewJSObjectFromMap(map);
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PutIntoWeakMap(weakmap, object, Handle<Smi>(Smi::FromInt(i), isolate));
16069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
16169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
16269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
16369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Check increased capacity.
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(128, ObjectHashTable::cast(weakmap->table())->Capacity());
16569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
16669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Force a full GC.
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(32, ObjectHashTable::cast(weakmap->table())->NumberOfElements());
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      0, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements());
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(false);
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(0, ObjectHashTable::cast(weakmap->table())->NumberOfElements());
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      32, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements());
17469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
17569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Check shrunk capacity.
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(32, ObjectHashTable::cast(weakmap->table())->Capacity());
17769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test that weak map values on an evacuation candidate which are not reachable
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// by other paths are correctly recorded in the slots buffer.
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress2060a) {
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (i::FLAG_never_compact) return;
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FLAG_always_compact = true;
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = GetIsolateFrom(&context);
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate->factory();
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap = isolate->heap();
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSFunction> function = factory->NewFunction(
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      factory->function_string());
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSObject> key = factory->NewJSObject(function);
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSWeakMap> weakmap = AllocateJSWeakMap(isolate);
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Start second old-space page so that values land on evacuation candidate.
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Page* first_page = heap->old_pointer_space()->anchor()->next_page();
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  factory->NewFixedArray(900 * KB / kPointerSize, TENURED);
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Fill up weak map with values on an evacuation candidate.
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(isolate);
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < 32; i++) {
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<JSObject> object = factory->NewJSObject(function, TENURED);
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(!heap->InNewSpace(object->address()));
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(!first_page->Contains(object->address()));
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PutIntoWeakMap(weakmap, key, object);
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Force compacting garbage collection.
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(FLAG_always_compact);
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(Heap::kNoGCFlags);
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test that weak map keys on an evacuation candidate which are reachable by
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// other strong paths are correctly recorded in the slots buffer.
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress2060b) {
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (i::FLAG_never_compact) return;
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FLAG_always_compact = true;
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FLAG_verify_heap = true;
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = GetIsolateFrom(&context);
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate->factory();
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap = isolate->heap();
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSFunction> function = factory->NewFunction(
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      factory->function_string());
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Start second old-space page so that keys land on evacuation candidate.
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Page* first_page = heap->old_pointer_space()->anchor()->next_page();
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  factory->NewFixedArray(900 * KB / kPointerSize, TENURED);
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Fill up weak map with keys on an evacuation candidate.
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSObject> keys[32];
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 32; i++) {
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    keys[i] = factory->NewJSObject(function, TENURED);
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!heap->InNewSpace(keys[i]->address()));
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!first_page->Contains(keys[i]->address()));
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSWeakMap> weakmap = AllocateJSWeakMap(isolate);
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 32; i++) {
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PutIntoWeakMap(weakmap,
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   keys[i],
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Handle<Smi>(Smi::FromInt(i), isolate));
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Force compacting garbage collection. The subsequent collections are used
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to verify that key references were actually updated.
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(FLAG_always_compact);
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(Heap::kNoGCFlags);
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(Heap::kNoGCFlags);
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(Heap::kNoGCFlags);
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress399527) {
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap = isolate->heap();
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HandleScope scope(isolate);
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocateJSWeakMap(isolate);
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SimulateIncrementalMarking(heap);
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The weak map is marked black here but leaving the handle scope will make
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the object unreachable. Aborting incremental marking will clear all the
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // marking bits which makes the weak map garbage.
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
275