Line data Source code
1 : // Copyright 2017 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include <stdlib.h>
6 : #include <sstream>
7 : #include <utility>
8 :
9 : #include "src/api.h"
10 : #include "src/objects-inl.h"
11 : #include "src/objects.h"
12 : #include "src/v8.h"
13 :
14 : #include "test/cctest/cctest.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 60 : int AddToSetAndGetHash(Isolate* isolate, Handle<JSObject> obj,
20 : bool has_fast_properties) {
21 60 : CHECK_EQ(has_fast_properties, obj->HasFastProperties());
22 60 : CHECK_EQ(isolate->heap()->undefined_value(), obj->GetHash());
23 60 : Handle<OrderedHashSet> set = isolate->factory()->NewOrderedHashSet();
24 60 : OrderedHashSet::Add(set, obj);
25 60 : CHECK_EQ(has_fast_properties, obj->HasFastProperties());
26 120 : return Smi::ToInt(obj->GetHash());
27 : }
28 :
29 24 : void CheckFastObject(Isolate* isolate, Handle<JSObject> obj, int hash) {
30 24 : CHECK(obj->HasFastProperties());
31 24 : CHECK(obj->raw_properties_or_hash()->IsPropertyArray());
32 48 : CHECK_EQ(Smi::FromInt(hash), obj->GetHash());
33 24 : CHECK_EQ(hash, obj->property_array()->Hash());
34 24 : }
35 :
36 18 : void CheckDictionaryObject(Isolate* isolate, Handle<JSObject> obj, int hash) {
37 18 : CHECK(!obj->HasFastProperties());
38 18 : CHECK(obj->raw_properties_or_hash()->IsDictionary());
39 36 : CHECK_EQ(Smi::FromInt(hash), obj->GetHash());
40 18 : CHECK_EQ(hash, obj->property_dictionary()->Hash());
41 18 : }
42 :
43 23724 : TEST(AddHashCodeToFastObjectWithoutProperties) {
44 6 : CcTest::InitializeVM();
45 6 : v8::HandleScope scope(CcTest::isolate());
46 : Isolate* isolate = CcTest::i_isolate();
47 :
48 : Handle<JSObject> obj =
49 6 : isolate->factory()->NewJSObject(isolate->object_function());
50 6 : CHECK(obj->HasFastProperties());
51 :
52 6 : int hash = AddToSetAndGetHash(isolate, obj, true);
53 6 : CHECK_EQ(Smi::FromInt(hash), obj->raw_properties_or_hash());
54 6 : }
55 :
56 23724 : TEST(AddHashCodeToFastObjectWithInObjectProperties) {
57 6 : CcTest::InitializeVM();
58 6 : v8::HandleScope scope(CcTest::isolate());
59 : Isolate* isolate = CcTest::i_isolate();
60 :
61 : const char* source = " var x = { a: 1};";
62 : CompileRun(source);
63 :
64 6 : Handle<JSObject> obj = GetGlobal<JSObject>("x");
65 6 : CHECK_EQ(isolate->heap()->empty_fixed_array(), obj->raw_properties_or_hash());
66 :
67 6 : int hash = AddToSetAndGetHash(isolate, obj, true);
68 6 : CHECK_EQ(Smi::FromInt(hash), obj->raw_properties_or_hash());
69 6 : }
70 :
71 23724 : TEST(AddHashCodeToFastObjectWithPropertiesArray) {
72 6 : CcTest::InitializeVM();
73 6 : v8::HandleScope scope(CcTest::isolate());
74 : Isolate* isolate = CcTest::i_isolate();
75 :
76 : const char* source =
77 : " var x = {}; "
78 : " x.a = 1; x.b = 2; x.c = 3; x.d = 4; x.e = 5; ";
79 : CompileRun(source);
80 :
81 6 : Handle<JSObject> obj = GetGlobal<JSObject>("x");
82 6 : CHECK(obj->HasFastProperties());
83 :
84 6 : int hash = AddToSetAndGetHash(isolate, obj, true);
85 6 : CheckFastObject(isolate, obj, hash);
86 6 : }
87 :
88 23724 : TEST(AddHashCodeToSlowObject) {
89 6 : CcTest::InitializeVM();
90 6 : v8::HandleScope scope(CcTest::isolate());
91 : Isolate* isolate = CcTest::i_isolate();
92 :
93 : Handle<JSObject> obj =
94 6 : isolate->factory()->NewJSObject(isolate->object_function());
95 6 : CHECK(obj->HasFastProperties());
96 : JSObject::NormalizeProperties(obj, CLEAR_INOBJECT_PROPERTIES, 0,
97 6 : "cctest/test-hashcode");
98 6 : CHECK(obj->raw_properties_or_hash()->IsDictionary());
99 :
100 6 : int hash = AddToSetAndGetHash(isolate, obj, false);
101 6 : CheckDictionaryObject(isolate, obj, hash);
102 6 : }
103 :
104 23724 : TEST(TransitionFastWithInObjectToFastWithPropertyArray) {
105 6 : CcTest::InitializeVM();
106 6 : v8::HandleScope scope(CcTest::isolate());
107 : Isolate* isolate = CcTest::i_isolate();
108 :
109 : const char* source =
110 : " var x = { };"
111 : " x.a = 1; x.b = 2; x.c = 3; x.d = 4;";
112 : CompileRun(source);
113 :
114 6 : Handle<JSObject> obj = GetGlobal<JSObject>("x");
115 6 : CHECK(obj->HasFastProperties());
116 :
117 6 : int hash = AddToSetAndGetHash(isolate, obj, true);
118 6 : CHECK_EQ(Smi::FromInt(hash), obj->raw_properties_or_hash());
119 :
120 : int length = obj->property_array()->length();
121 : CompileRun("x.e = 5;");
122 6 : CHECK(obj->property_array()->length() > length);
123 6 : CheckFastObject(isolate, obj, hash);
124 6 : }
125 :
126 23724 : TEST(TransitionFastWithPropertyArray) {
127 6 : CcTest::InitializeVM();
128 6 : v8::HandleScope scope(CcTest::isolate());
129 : Isolate* isolate = CcTest::i_isolate();
130 :
131 : const char* source =
132 : " var x = { };"
133 : " x.a = 1; x.b = 2; x.c = 3; x.d = 4; x.e = 5; ";
134 : CompileRun(source);
135 :
136 6 : Handle<JSObject> obj = GetGlobal<JSObject>("x");
137 6 : CHECK(obj->raw_properties_or_hash()->IsPropertyArray());
138 :
139 6 : int hash = AddToSetAndGetHash(isolate, obj, true);
140 6 : CHECK_EQ(hash, obj->property_array()->Hash());
141 :
142 : int length = obj->property_array()->length();
143 : CompileRun("x.f = 2; x.g = 5; x.h = 2");
144 6 : CHECK(obj->property_array()->length() > length);
145 6 : CheckFastObject(isolate, obj, hash);
146 6 : }
147 :
148 23724 : TEST(TransitionFastWithPropertyArrayToSlow) {
149 6 : CcTest::InitializeVM();
150 6 : v8::HandleScope scope(CcTest::isolate());
151 : Isolate* isolate = CcTest::i_isolate();
152 :
153 : const char* source =
154 : " var x = { };"
155 : " x.a = 1; x.b = 2; x.c = 3; x.d = 4; x.e = 5; ";
156 : CompileRun(source);
157 :
158 6 : Handle<JSObject> obj = GetGlobal<JSObject>("x");
159 6 : CHECK(obj->raw_properties_or_hash()->IsPropertyArray());
160 :
161 6 : int hash = AddToSetAndGetHash(isolate, obj, true);
162 6 : CHECK(obj->raw_properties_or_hash()->IsPropertyArray());
163 6 : CHECK_EQ(hash, obj->property_array()->Hash());
164 :
165 : JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 0,
166 6 : "cctest/test-hashcode");
167 6 : CheckDictionaryObject(isolate, obj, hash);
168 6 : }
169 :
170 23724 : TEST(TransitionSlowToSlow) {
171 6 : CcTest::InitializeVM();
172 6 : v8::HandleScope scope(CcTest::isolate());
173 : Isolate* isolate = CcTest::i_isolate();
174 :
175 : const char* source = " var x = {}; ";
176 : CompileRun(source);
177 :
178 6 : Handle<JSObject> obj = GetGlobal<JSObject>("x");
179 : JSObject::NormalizeProperties(obj, CLEAR_INOBJECT_PROPERTIES, 0,
180 6 : "cctest/test-hashcode");
181 6 : CHECK(obj->raw_properties_or_hash()->IsDictionary());
182 :
183 6 : int hash = AddToSetAndGetHash(isolate, obj, false);
184 6 : CHECK_EQ(hash, obj->property_dictionary()->Hash());
185 :
186 : int length = obj->property_dictionary()->length();
187 : CompileRun("for(var i = 0; i < 10; i++) { x['f'+i] = i };");
188 6 : CHECK(obj->property_dictionary()->length() > length);
189 6 : CheckDictionaryObject(isolate, obj, hash);
190 6 : }
191 :
192 23724 : TEST(TransitionSlowToFastWithoutProperties) {
193 6 : CcTest::InitializeVM();
194 6 : v8::HandleScope scope(CcTest::isolate());
195 : Isolate* isolate = CcTest::i_isolate();
196 :
197 : Handle<JSObject> obj =
198 6 : isolate->factory()->NewJSObject(isolate->object_function());
199 : JSObject::NormalizeProperties(obj, CLEAR_INOBJECT_PROPERTIES, 0,
200 6 : "cctest/test-hashcode");
201 6 : CHECK(obj->raw_properties_or_hash()->IsDictionary());
202 :
203 6 : int hash = AddToSetAndGetHash(isolate, obj, false);
204 6 : CHECK_EQ(hash, obj->property_dictionary()->Hash());
205 :
206 6 : JSObject::MigrateSlowToFast(obj, 0, "cctest/test-hashcode");
207 12 : CHECK_EQ(Smi::FromInt(hash), obj->GetHash());
208 6 : }
209 :
210 23724 : TEST(TransitionSlowToFastWithPropertyArray) {
211 6 : CcTest::InitializeVM();
212 6 : v8::HandleScope scope(CcTest::isolate());
213 : Isolate* isolate = CcTest::i_isolate();
214 :
215 : const char* source =
216 : " var x = Object.create(null); "
217 : " for(var i = 0; i < 10; i++) { x['f'+i] = i }; ";
218 : CompileRun(source);
219 :
220 6 : Handle<JSObject> obj = GetGlobal<JSObject>("x");
221 6 : CHECK(obj->raw_properties_or_hash()->IsDictionary());
222 :
223 6 : int hash = AddToSetAndGetHash(isolate, obj, false);
224 6 : CHECK_EQ(hash, obj->property_dictionary()->Hash());
225 :
226 6 : JSObject::MigrateSlowToFast(obj, 0, "cctest/test-hashcode");
227 6 : CheckFastObject(isolate, obj, hash);
228 6 : }
229 :
230 : } // namespace internal
231 71154 : } // namespace v8
|