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 "src/v8.h"
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h"
3069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/api.h"
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h"
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/execution.h"
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/factory.h"
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/global-handles.h"
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h"
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/objects.h"
3869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
3969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochusing namespace v8::internal;
4069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace {
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename HashMap>
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TestHashMap(Handle<HashMap> table) {
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate->factory();
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSObject> a = factory->NewJSArray(7);
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSObject> b = factory->NewJSArray(11);
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  table = HashMap::Put(table, a, b);
5269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(table->NumberOfElements(), 1);
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(table->Lookup(a), *b);
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // When the key does not exist in the map, Lookup returns the hole.
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(table->Lookup(b), CcTest::heap()->the_hole_value());
5669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
5769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Keys still have to be valid after objects were moved.
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectGarbage(NEW_SPACE);
5969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(table->NumberOfElements(), 1);
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(table->Lookup(a), *b);
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(table->Lookup(b), CcTest::heap()->the_hole_value());
6269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
6369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Keys that are overwritten should not change number of elements.
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  table = HashMap::Put(table, a, factory->NewJSArray(13));
6569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(table->NumberOfElements(), 1);
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_NE(table->Lookup(a), *b);
6769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Keys that have been removed are mapped to the hole.
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool was_present = false;
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  table = HashMap::Remove(table, a, &was_present);
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(was_present);
7269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(table->NumberOfElements(), 0);
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(table->Lookup(a), CcTest::heap()->the_hole_value());
7469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Keys should map back to their respective values and also should get
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // an identity hash code generated.
7769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  for (int i = 0; i < 100; i++) {
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<JSReceiver> key = factory->NewJSArray(7);
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<JSObject> value = factory->NewJSArray(11);
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table = HashMap::Put(table, key, value);
8169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK_EQ(table->NumberOfElements(), i + 1);
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_NE(table->FindEntry(key), HashMap::kNotFound);
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(table->Lookup(key), *value);
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(key->GetIdentityHash()->IsSmi());
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Keys never added to the map which already have an identity hash
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // code should not be found.
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < 100; i++) {
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<JSReceiver> key = factory->NewJSArray(7);
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(JSReceiver::GetOrCreateIdentityHash(key)->IsSmi());
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(table->FindEntry(key), HashMap::kNotFound);
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(table->Lookup(key), CcTest::heap()->the_hole_value());
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(key->GetIdentityHash()->IsSmi());
9569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
9669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Keys that don't have an identity hash should not be found and also
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // should not get an identity hash code generated.
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < 100; i++) {
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<JSReceiver> key = factory->NewJSArray(7);
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(table->Lookup(key), CcTest::heap()->the_hole_value());
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* identity_hash = key->GetIdentityHash();
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(identity_hash, CcTest::heap()->undefined_value());
10469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
10569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(HashMap) {
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestHashMap(ObjectHashTable::New(isolate, 23));
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestHashMap(isolate->factory()->NewOrderedHashMap());
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ObjectHashTableTest: public ObjectHashTable {
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void insert(int entry, int key, int value) {
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set(EntryToIndex(entry), Smi::FromInt(key));
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set(EntryToIndex(entry) + 1, Smi::FromInt(value));
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int lookup(int key) {
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Object> key_obj(Smi::FromInt(key), GetIsolate());
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Smi::cast(Lookup(key_obj))->value();
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int capacity() {
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Capacity();
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(HashTableRehash) {
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext context;
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test almost filled table.
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 100);
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ObjectHashTableTest* t = reinterpret_cast<ObjectHashTableTest*>(*table);
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int capacity = t->capacity();
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < capacity - 1; i++) {
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      t->insert(i, i * i, i);
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t->Rehash(handle(Smi::FromInt(0), isolate));
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < capacity - 1; i++) {
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(i, t->lookup(i * i));
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test half-filled table.
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 100);
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ObjectHashTableTest* t = reinterpret_cast<ObjectHashTableTest*>(*table);
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int capacity = t->capacity();
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < capacity / 2; i++) {
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      t->insert(i, i * i, i);
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t->Rehash(handle(Smi::FromInt(0), isolate));
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < capacity / 2; i++) {
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(i, t->lookup(i * i));
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class HashSet>
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TestHashSetCausesGC(Handle<HashSet> table) {
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate->factory();
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSObject> key = factory->NewJSArray(0);
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> key_obj = v8::Utils::ToLocal(key);
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Force allocation of hash table backing store for hidden properties.
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  key_obj->SetHiddenValue(v8_str("key 1"), v8_str("val 1"));
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  key_obj->SetHiddenValue(v8_str("key 2"), v8_str("val 2"));
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  key_obj->SetHiddenValue(v8_str("key 3"), v8_str("val 3"));
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Simulate a full heap so that generating an identity hash code
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in subsequent calls will request GC.
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimulateFullSpace(CcTest::heap()->new_space());
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimulateFullSpace(CcTest::heap()->old_pointer_space());
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Calling Contains() should not cause GC ever.
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int gc_count = isolate->heap()->gc_count();
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!table->Contains(key));
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(gc_count == isolate->heap()->gc_count());
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calling Remove() will not cause GC in this case.
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool was_present = false;
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  table = HashSet::Remove(table, key, &was_present);
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!was_present);
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(gc_count == isolate->heap()->gc_count());
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calling Add() should cause GC.
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  table = HashSet::Add(table, key);
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(gc_count < isolate->heap()->gc_count());
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ObjectHashSetCausesGC) {
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_stress_compaction = false;
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestHashSetCausesGC(isolate->factory()->NewOrderedHashSet());
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class HashMap>
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void TestHashMapCausesGC(Handle<HashMap> table) {
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate->factory();
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSObject> key = factory->NewJSArray(0);
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> key_obj = v8::Utils::ToLocal(key);
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Force allocation of hash table backing store for hidden properties.
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  key_obj->SetHiddenValue(v8_str("key 1"), v8_str("val 1"));
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  key_obj->SetHiddenValue(v8_str("key 2"), v8_str("val 2"));
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  key_obj->SetHiddenValue(v8_str("key 3"), v8_str("val 3"));
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Simulate a full heap so that generating an identity hash code
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in subsequent calls will request GC.
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimulateFullSpace(CcTest::heap()->new_space());
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimulateFullSpace(CcTest::heap()->old_pointer_space());
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Calling Lookup() should not cause GC ever.
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(table->Lookup(key)->IsTheHole());
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Calling Put() should request GC by returning a failure.
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int gc_count = isolate->heap()->gc_count();
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HashMap::Put(table, key, key);
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(gc_count < isolate->heap()->gc_count());
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ObjectHashTableCausesGC) {
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_stress_compaction = false;
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(context->GetIsolate());
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestHashMapCausesGC(ObjectHashTable::New(isolate, 1));
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TestHashMapCausesGC(isolate->factory()->NewOrderedHashMap());
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
255