1// Copyright 2011 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include "v8.h" 29 30#include "api.h" 31#include "debug.h" 32#include "execution.h" 33#include "factory.h" 34#include "macro-assembler.h" 35#include "objects.h" 36#include "global-handles.h" 37#include "cctest.h" 38 39using namespace v8::internal; 40 41 42TEST(ObjectHashTable) { 43 v8::HandleScope scope; 44 LocalContext context; 45 Handle<ObjectHashTable> table = FACTORY->NewObjectHashTable(23); 46 Handle<JSObject> a = FACTORY->NewJSArray(7); 47 Handle<JSObject> b = FACTORY->NewJSArray(11); 48 table = PutIntoObjectHashTable(table, a, b); 49 CHECK_EQ(table->NumberOfElements(), 1); 50 CHECK_EQ(table->Lookup(*a), *b); 51 CHECK_EQ(table->Lookup(*b), HEAP->undefined_value()); 52 53 // Keys still have to be valid after objects were moved. 54 HEAP->CollectGarbage(NEW_SPACE); 55 CHECK_EQ(table->NumberOfElements(), 1); 56 CHECK_EQ(table->Lookup(*a), *b); 57 CHECK_EQ(table->Lookup(*b), HEAP->undefined_value()); 58 59 // Keys that are overwritten should not change number of elements. 60 table = PutIntoObjectHashTable(table, a, FACTORY->NewJSArray(13)); 61 CHECK_EQ(table->NumberOfElements(), 1); 62 CHECK_NE(table->Lookup(*a), *b); 63 64 // Keys mapped to undefined should be removed permanently. 65 table = PutIntoObjectHashTable(table, a, FACTORY->undefined_value()); 66 CHECK_EQ(table->NumberOfElements(), 0); 67 CHECK_EQ(table->NumberOfDeletedElements(), 1); 68 CHECK_EQ(table->Lookup(*a), HEAP->undefined_value()); 69 70 // Keys should map back to their respective values and also should get 71 // an identity hash code generated. 72 for (int i = 0; i < 100; i++) { 73 Handle<JSObject> key = FACTORY->NewJSArray(7); 74 Handle<JSObject> value = FACTORY->NewJSArray(11); 75 table = PutIntoObjectHashTable(table, key, value); 76 CHECK_EQ(table->NumberOfElements(), i + 1); 77 CHECK_NE(table->FindEntry(*key), ObjectHashTable::kNotFound); 78 CHECK_EQ(table->Lookup(*key), *value); 79 CHECK(key->GetIdentityHash(OMIT_CREATION)->ToObjectChecked()->IsSmi()); 80 } 81 82 // Keys never added to the map which already have an identity hash 83 // code should not be found. 84 for (int i = 0; i < 100; i++) { 85 Handle<JSObject> key = FACTORY->NewJSArray(7); 86 CHECK(key->GetIdentityHash(ALLOW_CREATION)->ToObjectChecked()->IsSmi()); 87 CHECK_EQ(table->FindEntry(*key), ObjectHashTable::kNotFound); 88 CHECK_EQ(table->Lookup(*key), HEAP->undefined_value()); 89 CHECK(key->GetIdentityHash(OMIT_CREATION)->ToObjectChecked()->IsSmi()); 90 } 91 92 // Keys that don't have an identity hash should not be found and also 93 // should not get an identity hash code generated. 94 for (int i = 0; i < 100; i++) { 95 Handle<JSObject> key = FACTORY->NewJSArray(7); 96 CHECK_EQ(table->Lookup(*key), HEAP->undefined_value()); 97 CHECK_EQ(key->GetIdentityHash(OMIT_CREATION), HEAP->undefined_value()); 98 } 99} 100 101 102#ifdef DEBUG 103TEST(ObjectHashSetCausesGC) { 104 v8::HandleScope scope; 105 LocalContext context; 106 Handle<ObjectHashSet> table = FACTORY->NewObjectHashSet(1); 107 Handle<JSObject> key = FACTORY->NewJSArray(0); 108 109 // Simulate a full heap so that generating an identity hash code 110 // in subsequent calls will request GC. 111 FLAG_gc_interval = 0; 112 113 // Calling Contains() should not cause GC ever. 114 CHECK(!table->Contains(*key)); 115 116 // Calling Remove() should not cause GC ever. 117 CHECK(!table->Remove(*key)->IsFailure()); 118 119 // Calling Add() should request GC by returning a failure. 120 CHECK(table->Add(*key)->IsRetryAfterGC()); 121} 122#endif 123 124 125#ifdef DEBUG 126TEST(ObjectHashTableCausesGC) { 127 v8::HandleScope scope; 128 LocalContext context; 129 Handle<ObjectHashTable> table = FACTORY->NewObjectHashTable(1); 130 Handle<JSObject> key = FACTORY->NewJSArray(0); 131 132 // Simulate a full heap so that generating an identity hash code 133 // in subsequent calls will request GC. 134 FLAG_gc_interval = 0; 135 136 // Calling Lookup() should not cause GC ever. 137 CHECK(table->Lookup(*key)->IsUndefined()); 138 139 // Calling Put() should request GC by returning a failure. 140 CHECK(table->Put(*key, *key)->IsRetryAfterGC()); 141} 142#endif 143