1ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// Copyright 2011 the V8 project authors. All rights reserved.
2ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// Redistribution and use in source and binary forms, with or without
3ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// modification, are permitted provided that the following conditions are
4ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// met:
5ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//
6ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//     * Redistributions of source code must retain the above copyright
7ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       notice, this list of conditions and the following disclaimer.
8ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//     * Redistributions in binary form must reproduce the above
9ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       copyright notice, this list of conditions and the following
10ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       disclaimer in the documentation and/or other materials provided
11ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       with the distribution.
12ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//     * Neither the name of Google Inc. nor the names of its
13ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       contributors may be used to endorse or promote products derived
14ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       from this software without specific prior written permission.
15ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//
16ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
284f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org#include <utility>
294f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org
30196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
31ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
32196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/global-handles.h"
33196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/snapshot.h"
34196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/cctest.h"
35ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
36ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgusing namespace v8::internal;
37ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
38ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
39ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgstatic Isolate* GetIsolateFrom(LocalContext* context) {
40ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  return reinterpret_cast<Isolate*>((*context)->GetIsolate());
41ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
42ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
43ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
44ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgstatic Handle<JSWeakSet> AllocateJSWeakSet(Isolate* isolate) {
45ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Factory* factory = isolate->factory();
46ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Handle<Map> map = factory->NewMap(JS_WEAK_SET_TYPE, JSWeakSet::kSize);
47ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Handle<JSObject> weakset_obj = factory->NewJSObjectFromMap(map);
48ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Handle<JSWeakSet> weakset(JSWeakSet::cast(*weakset_obj));
49e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  // Do not leak handles for the hash table, it would make entries strong.
50e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  {
51e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org    HandleScope scope(isolate);
52e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org    Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 1);
53e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org    weakset->set_table(*table);
54e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  }
55ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  return weakset;
56ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
57ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
58ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgstatic void PutIntoWeakSet(Handle<JSWeakSet> weakset,
59ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                           Handle<JSObject> key,
60ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                           Handle<Object> value) {
61057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  Handle<ObjectHashTable> table = ObjectHashTable::Put(
62ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      Handle<ObjectHashTable>(ObjectHashTable::cast(weakset->table())),
63ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      Handle<JSObject>(JSObject::cast(*key)),
64ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      value);
65ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  weakset->set_table(*table);
66ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
67ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
68ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgstatic int NumberOfWeakCalls = 0;
694f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.orgstatic void WeakPointerCallback(
704f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    const v8::WeakCallbackData<v8::Value, void>& data) {
714f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  std::pair<v8::Persistent<v8::Value>*, int>* p =
724f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org      reinterpret_cast<std::pair<v8::Persistent<v8::Value>*, int>*>(
734f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org          data.GetParameter());
74e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(1234, p->second);
75ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  NumberOfWeakCalls++;
764f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org  p->first->Reset();
77ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
78ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
79ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
80ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgTEST(WeakSet_Weakness) {
81ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  FLAG_incremental_marking = false;
82ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  LocalContext context;
83ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Isolate* isolate = GetIsolateFrom(&context);
84ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Factory* factory = isolate->factory();
85ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Heap* heap = isolate->heap();
86ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  HandleScope scope(isolate);
87ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
88ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  GlobalHandles* global_handles = isolate->global_handles();
89ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
90ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Keep global reference to the key.
91ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Handle<Object> key;
92ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  {
93ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    HandleScope scope(isolate);
94ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
95ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    Handle<JSObject> object = factory->NewJSObjectFromMap(map);
96ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    key = global_handles->Create(*object);
97ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
98ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK(!global_handles->IsWeak(key.location()));
99ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
100ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Put entry into weak set.
101ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  {
102ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    HandleScope scope(isolate);
103ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    PutIntoWeakSet(weakset,
104ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                   Handle<JSObject>(JSObject::cast(*key)),
105ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                   Handle<Smi>(Smi::FromInt(23), isolate));
106ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
107ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(1, ObjectHashTable::cast(weakset->table())->NumberOfElements());
108ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
109ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Force a full GC.
110ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  heap->CollectAllGarbage(false);
111ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(0, NumberOfWeakCalls);
112ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(1, ObjectHashTable::cast(weakset->table())->NumberOfElements());
113ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(
114ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      0, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
115ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
116ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Make the global reference to the key weak.
117ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  {
118ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    HandleScope scope(isolate);
1194f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    std::pair<Handle<Object>*, int> handle_and_id(&key, 1234);
1204f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    GlobalHandles::MakeWeak(key.location(),
1214f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org                            reinterpret_cast<void*>(&handle_and_id),
1224f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org                            &WeakPointerCallback);
123ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
124ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK(global_handles->IsWeak(key.location()));
125ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
126ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Force a full GC.
127ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Perform two consecutive GCs because the first one will only clear
128ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // weak references whereas the second one will also clear weak sets.
129ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  heap->CollectAllGarbage(false);
130ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(1, NumberOfWeakCalls);
131ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(1, ObjectHashTable::cast(weakset->table())->NumberOfElements());
132ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(
133ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      0, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
134ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  heap->CollectAllGarbage(false);
135ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(1, NumberOfWeakCalls);
136ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(0, ObjectHashTable::cast(weakset->table())->NumberOfElements());
137ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(
138ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      1, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
139ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
140ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
141ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
142ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgTEST(WeakSet_Shrinking) {
143ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  LocalContext context;
144ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Isolate* isolate = GetIsolateFrom(&context);
145ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Factory* factory = isolate->factory();
146ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Heap* heap = isolate->heap();
147ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  HandleScope scope(isolate);
148ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
149ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
150ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Check initial capacity.
151ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(32, ObjectHashTable::cast(weakset->table())->Capacity());
152ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
153ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Fill up weak set to trigger capacity change.
154ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  {
155ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    HandleScope scope(isolate);
156ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
157ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    for (int i = 0; i < 32; i++) {
158ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      Handle<JSObject> object = factory->NewJSObjectFromMap(map);
159ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      PutIntoWeakSet(weakset, object, Handle<Smi>(Smi::FromInt(i), isolate));
160ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    }
161ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
162ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
163ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Check increased capacity.
164ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(128, ObjectHashTable::cast(weakset->table())->Capacity());
165ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
166ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Force a full GC.
167ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(32, ObjectHashTable::cast(weakset->table())->NumberOfElements());
168ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(
169ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      0, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
170ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  heap->CollectAllGarbage(false);
171ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(0, ObjectHashTable::cast(weakset->table())->NumberOfElements());
172ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(
173ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      32, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
174ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
175ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Check shrunk capacity.
176ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK_EQ(32, ObjectHashTable::cast(weakset->table())->Capacity());
177ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
178ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
179ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
180ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// Test that weak set values on an evacuation candidate which are not reachable
181ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// by other paths are correctly recorded in the slots buffer.
182ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgTEST(WeakSet_Regress2060a) {
183c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org  if (i::FLAG_never_compact) return;
184ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  FLAG_always_compact = true;
185ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  LocalContext context;
186ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Isolate* isolate = GetIsolateFrom(&context);
187ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Factory* factory = isolate->factory();
188ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Heap* heap = isolate->heap();
189ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  HandleScope scope(isolate);
1903c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  Handle<JSFunction> function = factory->NewFunction(
1913c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      factory->function_string());
192ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Handle<JSObject> key = factory->NewJSObject(function);
193ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
194ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
195ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Start second old-space page so that values land on evacuation candidate.
196ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Page* first_page = heap->old_pointer_space()->anchor()->next_page();
197ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  factory->NewFixedArray(900 * KB / kPointerSize, TENURED);
198ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
199ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Fill up weak set with values on an evacuation candidate.
200ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  {
201ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    HandleScope scope(isolate);
202ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    for (int i = 0; i < 32; i++) {
203ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      Handle<JSObject> object = factory->NewJSObject(function, TENURED);
204ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      CHECK(!heap->InNewSpace(object->address()));
205ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      CHECK(!first_page->Contains(object->address()));
206ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      PutIntoWeakSet(weakset, key, object);
207ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    }
208ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
209ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
210ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Force compacting garbage collection.
211ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK(FLAG_always_compact);
212ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  heap->CollectAllGarbage(Heap::kNoGCFlags);
213ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
214ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
215ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
216ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// Test that weak set keys on an evacuation candidate which are reachable by
217ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// other strong paths are correctly recorded in the slots buffer.
218ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgTEST(WeakSet_Regress2060b) {
219c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org  if (i::FLAG_never_compact) return;
220ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  FLAG_always_compact = true;
221ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#ifdef VERIFY_HEAP
222ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  FLAG_verify_heap = true;
223ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#endif
224ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
225ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  LocalContext context;
226ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Isolate* isolate = GetIsolateFrom(&context);
227ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Factory* factory = isolate->factory();
228ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Heap* heap = isolate->heap();
229ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  HandleScope scope(isolate);
2303c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  Handle<JSFunction> function = factory->NewFunction(
2313c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      factory->function_string());
232ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
233ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Start second old-space page so that keys land on evacuation candidate.
234ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Page* first_page = heap->old_pointer_space()->anchor()->next_page();
235ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  factory->NewFixedArray(900 * KB / kPointerSize, TENURED);
236ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
237ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Fill up weak set with keys on an evacuation candidate.
238ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Handle<JSObject> keys[32];
239ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  for (int i = 0; i < 32; i++) {
240ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    keys[i] = factory->NewJSObject(function, TENURED);
241ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    CHECK(!heap->InNewSpace(keys[i]->address()));
242ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    CHECK(!first_page->Contains(keys[i]->address()));
243ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
244ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
245ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  for (int i = 0; i < 32; i++) {
246ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    PutIntoWeakSet(weakset,
247ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                   keys[i],
248ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                   Handle<Smi>(Smi::FromInt(i), isolate));
249ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
250ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
251ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Force compacting garbage collection. The subsequent collections are used
252ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // to verify that key references were actually updated.
253ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK(FLAG_always_compact);
254ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  heap->CollectAllGarbage(Heap::kNoGCFlags);
255ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  heap->CollectAllGarbage(Heap::kNoGCFlags);
256ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  heap->CollectAllGarbage(Heap::kNoGCFlags);
257ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
258