Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: test/cctest/test-code-stub-assembler.cc

Issue 2028333002: Revert of Extend HasProperty stub with dictionary-mode and double-elements objects support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/compiler/test-code-stub-assembler.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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 "src/base/utils/random-number-generator.h"
6 #include "src/interface-descriptors.h"
7 #include "src/isolate.h"
8 #include "test/cctest/compiler/function-tester.h"
9
10 namespace v8 {
11 namespace internal {
12
13 using compiler::FunctionTester;
14 using compiler::Node;
15
16 class CodeStubAssemblerTester : public CodeStubAssembler {
17 public:
18 // Test generating code for a stub.
19 CodeStubAssemblerTester(Isolate* isolate,
20 const CallInterfaceDescriptor& descriptor)
21 : CodeStubAssembler(isolate, isolate->runtime_zone(), descriptor,
22 Code::ComputeFlags(Code::STUB), "test"),
23 zone_scope_(isolate->runtime_zone()),
24 scope_(isolate) {}
25
26 // Test generating code for a JS function (e.g. builtins).
27 CodeStubAssemblerTester(Isolate* isolate, int parameter_count)
28 : CodeStubAssembler(isolate, isolate->runtime_zone(), parameter_count,
29 Code::ComputeFlags(Code::FUNCTION), "test"),
30 zone_scope_(isolate->runtime_zone()),
31 scope_(isolate) {}
32
33 private:
34 ZoneScope zone_scope_;
35 HandleScope scope_;
36 LocalContext context_;
37 };
38
39 TEST(SimpleSmiReturn) {
40 Isolate* isolate(CcTest::InitIsolateOnce());
41 VoidDescriptor descriptor(isolate);
42 CodeStubAssemblerTester m(isolate, descriptor);
43 m.Return(m.SmiTag(m.Int32Constant(37)));
44 Handle<Code> code = m.GenerateCode();
45 FunctionTester ft(descriptor, code);
46 MaybeHandle<Object> result = ft.Call();
47 CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value());
48 }
49
50 TEST(SimpleIntPtrReturn) {
51 Isolate* isolate(CcTest::InitIsolateOnce());
52 VoidDescriptor descriptor(isolate);
53 CodeStubAssemblerTester m(isolate, descriptor);
54 int test;
55 m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test)));
56 Handle<Code> code = m.GenerateCode();
57 FunctionTester ft(descriptor, code);
58 MaybeHandle<Object> result = ft.Call();
59 CHECK_EQ(reinterpret_cast<intptr_t>(&test),
60 reinterpret_cast<intptr_t>(*result.ToHandleChecked()));
61 }
62
63 TEST(SimpleDoubleReturn) {
64 Isolate* isolate(CcTest::InitIsolateOnce());
65 VoidDescriptor descriptor(isolate);
66 CodeStubAssemblerTester m(isolate, descriptor);
67 m.Return(m.NumberConstant(0.5));
68 Handle<Code> code = m.GenerateCode();
69 FunctionTester ft(descriptor, code);
70 MaybeHandle<Object> result = ft.Call();
71 CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value());
72 }
73
74 TEST(SimpleCallRuntime1Arg) {
75 Isolate* isolate(CcTest::InitIsolateOnce());
76 VoidDescriptor descriptor(isolate);
77 CodeStubAssemblerTester m(isolate, descriptor);
78 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
79 Node* b = m.SmiTag(m.Int32Constant(0));
80 m.Return(m.CallRuntime(Runtime::kNumberToSmi, context, b));
81 Handle<Code> code = m.GenerateCode();
82 FunctionTester ft(descriptor, code);
83 MaybeHandle<Object> result = ft.Call();
84 CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
85 }
86
87 TEST(SimpleTailCallRuntime1Arg) {
88 Isolate* isolate(CcTest::InitIsolateOnce());
89 VoidDescriptor descriptor(isolate);
90 CodeStubAssemblerTester m(isolate, descriptor);
91 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
92 Node* b = m.SmiTag(m.Int32Constant(0));
93 m.TailCallRuntime(Runtime::kNumberToSmi, context, b);
94 Handle<Code> code = m.GenerateCode();
95 FunctionTester ft(descriptor, code);
96 MaybeHandle<Object> result = ft.Call();
97 CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
98 }
99
100 TEST(SimpleCallRuntime2Arg) {
101 Isolate* isolate(CcTest::InitIsolateOnce());
102 VoidDescriptor descriptor(isolate);
103 CodeStubAssemblerTester m(isolate, descriptor);
104 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
105 Node* a = m.SmiTag(m.Int32Constant(2));
106 Node* b = m.SmiTag(m.Int32Constant(4));
107 m.Return(m.CallRuntime(Runtime::kMathPow, context, a, b));
108 Handle<Code> code = m.GenerateCode();
109 FunctionTester ft(descriptor, code);
110 MaybeHandle<Object> result = ft.Call();
111 CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
112 }
113
114 TEST(SimpleTailCallRuntime2Arg) {
115 Isolate* isolate(CcTest::InitIsolateOnce());
116 VoidDescriptor descriptor(isolate);
117 CodeStubAssemblerTester m(isolate, descriptor);
118 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
119 Node* a = m.SmiTag(m.Int32Constant(2));
120 Node* b = m.SmiTag(m.Int32Constant(4));
121 m.TailCallRuntime(Runtime::kMathPow, context, a, b);
122 Handle<Code> code = m.GenerateCode();
123 FunctionTester ft(descriptor, code);
124 MaybeHandle<Object> result = ft.Call();
125 CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
126 }
127
128 TEST(VariableMerge1) {
129 Isolate* isolate(CcTest::InitIsolateOnce());
130 VoidDescriptor descriptor(isolate);
131 CodeStubAssemblerTester m(isolate, descriptor);
132 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
133 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
134 Node* temp = m.Int32Constant(0);
135 var1.Bind(temp);
136 m.Branch(m.Int32Constant(1), &l1, &l2);
137 m.Bind(&l1);
138 CHECK_EQ(var1.value(), temp);
139 m.Goto(&merge);
140 m.Bind(&l2);
141 CHECK_EQ(var1.value(), temp);
142 m.Goto(&merge);
143 m.Bind(&merge);
144 CHECK_EQ(var1.value(), temp);
145 }
146
147 TEST(VariableMerge2) {
148 Isolate* isolate(CcTest::InitIsolateOnce());
149 VoidDescriptor descriptor(isolate);
150 CodeStubAssemblerTester m(isolate, descriptor);
151 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
152 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
153 Node* temp = m.Int32Constant(0);
154 var1.Bind(temp);
155 m.Branch(m.Int32Constant(1), &l1, &l2);
156 m.Bind(&l1);
157 CHECK_EQ(var1.value(), temp);
158 m.Goto(&merge);
159 m.Bind(&l2);
160 Node* temp2 = m.Int32Constant(2);
161 var1.Bind(temp2);
162 CHECK_EQ(var1.value(), temp2);
163 m.Goto(&merge);
164 m.Bind(&merge);
165 CHECK_NE(var1.value(), temp);
166 }
167
168 TEST(VariableMerge3) {
169 Isolate* isolate(CcTest::InitIsolateOnce());
170 VoidDescriptor descriptor(isolate);
171 CodeStubAssemblerTester m(isolate, descriptor);
172 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
173 CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged);
174 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
175 Node* temp = m.Int32Constant(0);
176 var1.Bind(temp);
177 var2.Bind(temp);
178 m.Branch(m.Int32Constant(1), &l1, &l2);
179 m.Bind(&l1);
180 CHECK_EQ(var1.value(), temp);
181 m.Goto(&merge);
182 m.Bind(&l2);
183 Node* temp2 = m.Int32Constant(2);
184 var1.Bind(temp2);
185 CHECK_EQ(var1.value(), temp2);
186 m.Goto(&merge);
187 m.Bind(&merge);
188 CHECK_NE(var1.value(), temp);
189 CHECK_NE(var1.value(), temp2);
190 CHECK_EQ(var2.value(), temp);
191 }
192
193 TEST(VariableMergeBindFirst) {
194 Isolate* isolate(CcTest::InitIsolateOnce());
195 VoidDescriptor descriptor(isolate);
196 CodeStubAssemblerTester m(isolate, descriptor);
197 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
198 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m);
199 Node* temp = m.Int32Constant(0);
200 var1.Bind(temp);
201 m.Branch(m.Int32Constant(1), &l1, &l2);
202 m.Bind(&l1);
203 CHECK_EQ(var1.value(), temp);
204 m.Goto(&merge);
205 m.Bind(&merge);
206 CHECK(var1.value() != temp);
207 CHECK(var1.value() != nullptr);
208 m.Goto(&end);
209 m.Bind(&l2);
210 Node* temp2 = m.Int32Constant(2);
211 var1.Bind(temp2);
212 CHECK_EQ(var1.value(), temp2);
213 m.Goto(&merge);
214 m.Bind(&end);
215 CHECK(var1.value() != temp);
216 CHECK(var1.value() != nullptr);
217 }
218
219 TEST(VariableMergeSwitch) {
220 Isolate* isolate(CcTest::InitIsolateOnce());
221 VoidDescriptor descriptor(isolate);
222 CodeStubAssemblerTester m(isolate, descriptor);
223 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
224 CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m);
225 CodeStubAssembler::Label* labels[] = {&l1, &l2};
226 int32_t values[] = {1, 2};
227 Node* temp = m.Int32Constant(0);
228 var1.Bind(temp);
229 m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
230 m.Bind(&l1);
231 DCHECK_EQ(temp, var1.value());
232 m.Return(temp);
233 m.Bind(&l2);
234 DCHECK_EQ(temp, var1.value());
235 m.Return(temp);
236 m.Bind(&default_label);
237 DCHECK_EQ(temp, var1.value());
238 m.Return(temp);
239 }
240
241 TEST(FixedArrayAccessSmiIndex) {
242 Isolate* isolate(CcTest::InitIsolateOnce());
243 VoidDescriptor descriptor(isolate);
244 CodeStubAssemblerTester m(isolate, descriptor);
245 Handle<FixedArray> array = isolate->factory()->NewFixedArray(5);
246 array->set(4, Smi::FromInt(733));
247 m.Return(m.LoadFixedArrayElement(m.HeapConstant(array),
248 m.SmiTag(m.Int32Constant(4)), 0,
249 CodeStubAssembler::SMI_PARAMETERS));
250 Handle<Code> code = m.GenerateCode();
251 FunctionTester ft(descriptor, code);
252 MaybeHandle<Object> result = ft.Call();
253 CHECK_EQ(733, Handle<Smi>::cast(result.ToHandleChecked())->value());
254 }
255
256 TEST(LoadHeapNumberValue) {
257 Isolate* isolate(CcTest::InitIsolateOnce());
258 VoidDescriptor descriptor(isolate);
259 CodeStubAssemblerTester m(isolate, descriptor);
260 Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(1234);
261 m.Return(m.SmiTag(
262 m.ChangeFloat64ToUint32(m.LoadHeapNumberValue(m.HeapConstant(number)))));
263 Handle<Code> code = m.GenerateCode();
264 FunctionTester ft(descriptor, code);
265 MaybeHandle<Object> result = ft.Call();
266 CHECK_EQ(1234, Handle<Smi>::cast(result.ToHandleChecked())->value());
267 }
268
269 TEST(LoadInstanceType) {
270 Isolate* isolate(CcTest::InitIsolateOnce());
271 VoidDescriptor descriptor(isolate);
272 CodeStubAssemblerTester m(isolate, descriptor);
273 Handle<HeapObject> undefined = isolate->factory()->undefined_value();
274 m.Return(m.SmiTag(m.LoadInstanceType(m.HeapConstant(undefined))));
275 Handle<Code> code = m.GenerateCode();
276 FunctionTester ft(descriptor, code);
277 MaybeHandle<Object> result = ft.Call();
278 CHECK_EQ(InstanceType::ODDBALL_TYPE,
279 Handle<Smi>::cast(result.ToHandleChecked())->value());
280 }
281
282 namespace {
283
284 class TestBitField : public BitField<unsigned, 3, 3> {};
285
286 } // namespace
287
288 TEST(BitFieldDecode) {
289 Isolate* isolate(CcTest::InitIsolateOnce());
290 VoidDescriptor descriptor(isolate);
291 CodeStubAssemblerTester m(isolate, descriptor);
292 m.Return(m.SmiTag(m.BitFieldDecode<TestBitField>(m.Int32Constant(0x2f))));
293 Handle<Code> code = m.GenerateCode();
294 FunctionTester ft(descriptor, code);
295 MaybeHandle<Object> result = ft.Call();
296 // value = 00101111
297 // mask = 00111000
298 // result = 101
299 CHECK_EQ(5, Handle<Smi>::cast(result.ToHandleChecked())->value());
300 }
301
302 namespace {
303
304 Handle<JSFunction> CreateFunctionFromCode(int parameter_count_with_receiver,
305 Handle<Code> code) {
306 Isolate* isolate = code->GetIsolate();
307 Handle<String> name = isolate->factory()->InternalizeUtf8String("test");
308 Handle<JSFunction> function =
309 isolate->factory()->NewFunctionWithoutPrototype(name, code);
310 function->shared()->set_internal_formal_parameter_count(
311 parameter_count_with_receiver - 1); // Implicit undefined receiver.
312 return function;
313 }
314
315 } // namespace
316
317 TEST(JSFunction) {
318 const int kNumParams = 3; // Receiver, left, right.
319 Isolate* isolate(CcTest::InitIsolateOnce());
320 CodeStubAssemblerTester m(isolate, kNumParams);
321 m.Return(m.SmiTag(m.Int32Add(m.SmiToWord32(m.Parameter(1)),
322 m.SmiToWord32(m.Parameter(2)))));
323 Handle<Code> code = m.GenerateCode();
324 Handle<JSFunction> function = CreateFunctionFromCode(kNumParams, code);
325 Handle<Object> args[] = {Handle<Smi>(Smi::FromInt(23), isolate),
326 Handle<Smi>(Smi::FromInt(34), isolate)};
327 MaybeHandle<Object> result =
328 Execution::Call(isolate, function, isolate->factory()->undefined_value(),
329 arraysize(args), args);
330 CHECK_EQ(57, Handle<Smi>::cast(result.ToHandleChecked())->value());
331 }
332
333 TEST(SplitEdgeBranchMerge) {
334 Isolate* isolate(CcTest::InitIsolateOnce());
335 VoidDescriptor descriptor(isolate);
336 CodeStubAssemblerTester m(isolate, descriptor);
337 CodeStubAssembler::Label l1(&m), merge(&m);
338 m.Branch(m.Int32Constant(1), &l1, &merge);
339 m.Bind(&l1);
340 m.Goto(&merge);
341 m.Bind(&merge);
342 USE(m.GenerateCode());
343 }
344
345 TEST(SplitEdgeSwitchMerge) {
346 Isolate* isolate(CcTest::InitIsolateOnce());
347 VoidDescriptor descriptor(isolate);
348 CodeStubAssemblerTester m(isolate, descriptor);
349 CodeStubAssembler::Label l1(&m), l2(&m), l3(&m), default_label(&m);
350 CodeStubAssembler::Label* labels[] = {&l1, &l2};
351 int32_t values[] = {1, 2};
352 m.Branch(m.Int32Constant(1), &l3, &l1);
353 m.Bind(&l3);
354 m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
355 m.Bind(&l1);
356 m.Goto(&l2);
357 m.Bind(&l2);
358 m.Goto(&default_label);
359 m.Bind(&default_label);
360 USE(m.GenerateCode());
361 }
362
363 TEST(TestToConstant) {
364 Isolate* isolate(CcTest::InitIsolateOnce());
365 VoidDescriptor descriptor(isolate);
366 CodeStubAssemblerTester m(isolate, descriptor);
367 int32_t value32;
368 int64_t value64;
369 Node* a = m.Int32Constant(5);
370 CHECK(m.ToInt32Constant(a, value32));
371 CHECK(m.ToInt64Constant(a, value64));
372
373 a = m.Int64Constant(static_cast<int64_t>(1) << 32);
374 CHECK(!m.ToInt32Constant(a, value32));
375 CHECK(m.ToInt64Constant(a, value64));
376
377 a = m.Int64Constant(13);
378 CHECK(m.ToInt32Constant(a, value32));
379 CHECK(m.ToInt64Constant(a, value64));
380
381 a = m.UndefinedConstant();
382 CHECK(!m.ToInt32Constant(a, value32));
383 CHECK(!m.ToInt64Constant(a, value64));
384
385 a = m.UndefinedConstant();
386 CHECK(!m.ToInt32Constant(a, value32));
387 CHECK(!m.ToInt64Constant(a, value64));
388 }
389
390 TEST(ComputeIntegerHash) {
391 Isolate* isolate(CcTest::InitIsolateOnce());
392 const int param_count = 2;
393 CodeStubAssemblerTester m(isolate, param_count);
394 m.Return(m.SmiFromWord32(m.ComputeIntegerHash(
395 m.SmiToWord32(m.Parameter(0)), m.SmiToWord32(m.Parameter(1)))));
396
397 Handle<Code> code = m.GenerateCode();
398 FunctionTester ft(code, param_count);
399
400 Handle<Smi> hash_seed = isolate->factory()->hash_seed();
401
402 base::RandomNumberGenerator rand_gen(FLAG_random_seed);
403
404 for (int i = 0; i < 1024; i++) {
405 int k = rand_gen.NextInt(Smi::kMaxValue);
406
407 Handle<Smi> key(Smi::FromInt(k), isolate);
408 Handle<Object> result = ft.Call(key, hash_seed).ToHandleChecked();
409
410 uint32_t hash = ComputeIntegerHash(k, hash_seed->value());
411 Smi* expected = Smi::FromInt(hash & Smi::kMaxValue);
412 CHECK_EQ(expected, Smi::cast(*result));
413 }
414 }
415
416 TEST(TryToName) {
417 typedef CodeStubAssembler::Label Label;
418 typedef CodeStubAssembler::Variable Variable;
419 Isolate* isolate(CcTest::InitIsolateOnce());
420
421 const int param_count = 3;
422 CodeStubAssemblerTester m(isolate, param_count);
423
424 enum Result { kKeyIsIndex, kKeyIsUnique, kBailout };
425 {
426 Node* key = m.Parameter(0);
427 Node* expected_result = m.Parameter(1);
428 Node* expected_arg = m.Parameter(2);
429
430 Label passed(&m), failed(&m);
431 Label if_keyisindex(&m), if_keyisunique(&m), if_bailout(&m);
432 Variable var_index(&m, MachineRepresentation::kWord32);
433
434 m.TryToName(key, &if_keyisindex, &var_index, &if_keyisunique, &if_bailout);
435
436 m.Bind(&if_keyisindex);
437 m.GotoUnless(
438 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kKeyIsIndex))),
439 &failed);
440 m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_index.value()),
441 &passed, &failed);
442
443 m.Bind(&if_keyisunique);
444 m.GotoUnless(
445 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kKeyIsUnique))),
446 &failed);
447 m.Branch(m.WordEqual(expected_arg, key), &passed, &failed);
448
449 m.Bind(&if_bailout);
450 m.Branch(
451 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kBailout))),
452 &passed, &failed);
453
454 m.Bind(&passed);
455 m.Return(m.BooleanConstant(true));
456
457 m.Bind(&failed);
458 m.Return(m.BooleanConstant(false));
459 }
460
461 Handle<Code> code = m.GenerateCode();
462 FunctionTester ft(code, param_count);
463
464 Handle<Object> expect_index(Smi::FromInt(kKeyIsIndex), isolate);
465 Handle<Object> expect_unique(Smi::FromInt(kKeyIsUnique), isolate);
466 Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate);
467
468 {
469 // TryToName(<zero smi>) => if_keyisindex: smi value.
470 Handle<Object> key(Smi::FromInt(0), isolate);
471 ft.CheckTrue(key, expect_index, key);
472 }
473
474 {
475 // TryToName(<positive smi>) => if_keyisindex: smi value.
476 Handle<Object> key(Smi::FromInt(153), isolate);
477 ft.CheckTrue(key, expect_index, key);
478 }
479
480 {
481 // TryToName(<negative smi>) => bailout.
482 Handle<Object> key(Smi::FromInt(-1), isolate);
483 ft.CheckTrue(key, expect_bailout);
484 }
485
486 {
487 // TryToName(<symbol>) => if_keyisunique: <symbol>.
488 Handle<Object> key = isolate->factory()->NewSymbol();
489 ft.CheckTrue(key, expect_unique, key);
490 }
491
492 {
493 // TryToName(<internalized string>) => if_keyisunique: <internalized string>
494 Handle<Object> key = isolate->factory()->InternalizeUtf8String("test");
495 ft.CheckTrue(key, expect_unique, key);
496 }
497
498 {
499 // TryToName(<internalized number string>) => if_keyisindex: number.
500 Handle<Object> key = isolate->factory()->InternalizeUtf8String("153");
501 Handle<Object> index(Smi::FromInt(153), isolate);
502 ft.CheckTrue(key, expect_index, index);
503 }
504
505 {
506 // TryToName(<non-internalized string>) => bailout.
507 Handle<Object> key = isolate->factory()->NewStringFromAsciiChecked("test");
508 ft.CheckTrue(key, expect_bailout);
509 }
510 }
511
512 namespace {
513
514 template <typename Dictionary>
515 void TestNameDictionaryLookup() {
516 typedef CodeStubAssembler::Label Label;
517 typedef CodeStubAssembler::Variable Variable;
518 Isolate* isolate(CcTest::InitIsolateOnce());
519
520 const int param_count = 4;
521 CodeStubAssemblerTester m(isolate, param_count);
522
523 enum Result { kFound, kNotFound };
524 {
525 Node* dictionary = m.Parameter(0);
526 Node* unique_name = m.Parameter(1);
527 Node* expected_result = m.Parameter(2);
528 Node* expected_arg = m.Parameter(3);
529
530 Label passed(&m), failed(&m);
531 Label if_found(&m), if_not_found(&m);
532 Variable var_entry(&m, MachineRepresentation::kWord32);
533
534 m.NameDictionaryLookup<Dictionary>(dictionary, unique_name, &if_found,
535 &var_entry, &if_not_found);
536 m.Bind(&if_found);
537 m.GotoUnless(
538 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
539 &failed);
540 m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_entry.value()),
541 &passed, &failed);
542
543 m.Bind(&if_not_found);
544 m.Branch(
545 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
546 &passed, &failed);
547
548 m.Bind(&passed);
549 m.Return(m.BooleanConstant(true));
550
551 m.Bind(&failed);
552 m.Return(m.BooleanConstant(false));
553 }
554
555 Handle<Code> code = m.GenerateCode();
556 FunctionTester ft(code, param_count);
557
558 Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
559 Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
560
561 Handle<Dictionary> dictionary = Dictionary::New(isolate, 40);
562 PropertyDetails fake_details = PropertyDetails::Empty();
563
564 Factory* factory = isolate->factory();
565 Handle<Name> keys[] = {
566 factory->InternalizeUtf8String("0"),
567 factory->InternalizeUtf8String("42"),
568 factory->InternalizeUtf8String("-153"),
569 factory->InternalizeUtf8String("0.0"),
570 factory->InternalizeUtf8String("4.2"),
571 factory->InternalizeUtf8String(""),
572 factory->InternalizeUtf8String("name"),
573 factory->NewSymbol(),
574 factory->NewPrivateSymbol(),
575 };
576
577 for (size_t i = 0; i < arraysize(keys); i++) {
578 Handle<Object> value = factory->NewPropertyCell();
579 dictionary = Dictionary::Add(dictionary, keys[i], value, fake_details);
580 }
581
582 for (size_t i = 0; i < arraysize(keys); i++) {
583 int entry = dictionary->FindEntry(keys[i]);
584 CHECK_NE(Dictionary::kNotFound, entry);
585
586 Handle<Object> expected_entry(Smi::FromInt(entry), isolate);
587 ft.CheckTrue(dictionary, keys[i], expect_found, expected_entry);
588 }
589
590 Handle<Name> non_existing_keys[] = {
591 factory->InternalizeUtf8String("1"),
592 factory->InternalizeUtf8String("-42"),
593 factory->InternalizeUtf8String("153"),
594 factory->InternalizeUtf8String("-1.0"),
595 factory->InternalizeUtf8String("1.3"),
596 factory->InternalizeUtf8String("a"),
597 factory->InternalizeUtf8String("boom"),
598 factory->NewSymbol(),
599 factory->NewPrivateSymbol(),
600 };
601
602 for (size_t i = 0; i < arraysize(non_existing_keys); i++) {
603 int entry = dictionary->FindEntry(non_existing_keys[i]);
604 CHECK_EQ(Dictionary::kNotFound, entry);
605
606 ft.CheckTrue(dictionary, non_existing_keys[i], expect_not_found);
607 }
608 }
609
610 } // namespace
611
612 TEST(NameDictionaryLookup) { TestNameDictionaryLookup<NameDictionary>(); }
613
614 TEST(GlobalDictionaryLookup) { TestNameDictionaryLookup<GlobalDictionary>(); }
615
616 namespace {
617
618 template <typename Dictionary>
619 void TestNumberDictionaryLookup() {
620 typedef CodeStubAssembler::Label Label;
621 typedef CodeStubAssembler::Variable Variable;
622 Isolate* isolate(CcTest::InitIsolateOnce());
623
624 const int param_count = 4;
625 CodeStubAssemblerTester m(isolate, param_count);
626
627 enum Result { kFound, kNotFound };
628 {
629 Node* dictionary = m.Parameter(0);
630 Node* key = m.SmiToWord32(m.Parameter(1));
631 Node* expected_result = m.Parameter(2);
632 Node* expected_arg = m.Parameter(3);
633
634 Label passed(&m), failed(&m);
635 Label if_found(&m), if_not_found(&m);
636 Variable var_entry(&m, MachineRepresentation::kWord32);
637
638 m.NumberDictionaryLookup<Dictionary>(dictionary, key, &if_found, &var_entry,
639 &if_not_found);
640 m.Bind(&if_found);
641 m.GotoUnless(
642 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
643 &failed);
644 m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_entry.value()),
645 &passed, &failed);
646
647 m.Bind(&if_not_found);
648 m.Branch(
649 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
650 &passed, &failed);
651
652 m.Bind(&passed);
653 m.Return(m.BooleanConstant(true));
654
655 m.Bind(&failed);
656 m.Return(m.BooleanConstant(false));
657 }
658
659 Handle<Code> code = m.GenerateCode();
660 FunctionTester ft(code, param_count);
661
662 Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
663 Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
664
665 const int kKeysCount = 1000;
666 Handle<Dictionary> dictionary = Dictionary::New(isolate, kKeysCount);
667 uint32_t keys[kKeysCount];
668
669 Handle<Object> fake_value(Smi::FromInt(42), isolate);
670 PropertyDetails fake_details = PropertyDetails::Empty();
671
672 base::RandomNumberGenerator rand_gen(FLAG_random_seed);
673
674 for (int i = 0; i < kKeysCount; i++) {
675 int random_key = rand_gen.NextInt(Smi::kMaxValue);
676 keys[i] = static_cast<uint32_t>(random_key);
677
678 dictionary = Dictionary::Add(dictionary, keys[i], fake_value, fake_details);
679 }
680
681 // Now try querying existing keys.
682 for (int i = 0; i < kKeysCount; i++) {
683 int entry = dictionary->FindEntry(keys[i]);
684 CHECK_NE(Dictionary::kNotFound, entry);
685
686 Handle<Object> key(Smi::FromInt(keys[i]), isolate);
687 Handle<Object> expected_entry(Smi::FromInt(entry), isolate);
688 ft.CheckTrue(dictionary, key, expect_found, expected_entry);
689 }
690
691 // Now try querying random keys which do not exist in the dictionary.
692 for (int i = 0; i < kKeysCount;) {
693 int random_key = rand_gen.NextInt(Smi::kMaxValue);
694 int entry = dictionary->FindEntry(random_key);
695 if (entry != Dictionary::kNotFound) continue;
696 i++;
697
698 Handle<Object> key(Smi::FromInt(random_key), isolate);
699 ft.CheckTrue(dictionary, key, expect_not_found);
700 }
701 }
702
703 } // namespace
704
705 TEST(SeededNumberDictionaryLookup) {
706 TestNumberDictionaryLookup<SeededNumberDictionary>();
707 }
708
709 TEST(UnseededNumberDictionaryLookup) {
710 TestNumberDictionaryLookup<UnseededNumberDictionary>();
711 }
712
713 namespace {
714
715 void AddProperties(Handle<JSObject> object, Handle<Name> names[],
716 size_t count) {
717 Handle<Object> value(Smi::FromInt(42), object->GetIsolate());
718 for (size_t i = 0; i < count; i++) {
719 JSObject::AddProperty(object, names[i], value, NONE);
720 }
721 }
722
723 } // namespace
724
725 TEST(TryLookupProperty) {
726 typedef CodeStubAssembler::Label Label;
727 Isolate* isolate(CcTest::InitIsolateOnce());
728
729 const int param_count = 4;
730 CodeStubAssemblerTester m(isolate, param_count);
731
732 enum Result { kFound, kNotFound, kBailout };
733 {
734 Node* object = m.Parameter(0);
735 Node* unique_name = m.Parameter(1);
736 Node* expected_result = m.Parameter(2);
737
738 Label passed(&m), failed(&m);
739 Label if_found(&m), if_not_found(&m), if_bailout(&m);
740
741 Node* map = m.LoadMap(object);
742 Node* instance_type = m.LoadMapInstanceType(map);
743
744 m.TryLookupProperty(object, map, instance_type, unique_name, &if_found,
745 &if_not_found, &if_bailout);
746
747 m.Bind(&if_found);
748 m.Branch(m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
749 &passed, &failed);
750
751 m.Bind(&if_not_found);
752 m.Branch(
753 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
754 &passed, &failed);
755
756 m.Bind(&if_bailout);
757 m.Branch(
758 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kBailout))),
759 &passed, &failed);
760
761 m.Bind(&passed);
762 m.Return(m.BooleanConstant(true));
763
764 m.Bind(&failed);
765 m.Return(m.BooleanConstant(false));
766 }
767
768 Handle<Code> code = m.GenerateCode();
769 FunctionTester ft(code, param_count);
770
771 Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
772 Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
773 Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate);
774
775 Factory* factory = isolate->factory();
776 Handle<Name> names[] = {
777 factory->InternalizeUtf8String("a"),
778 factory->InternalizeUtf8String("bb"),
779 factory->InternalizeUtf8String("ccc"),
780 factory->InternalizeUtf8String("dddd"),
781 factory->InternalizeUtf8String("eeeee"),
782 factory->InternalizeUtf8String(""),
783 factory->InternalizeUtf8String("name"),
784 factory->NewSymbol(),
785 factory->NewPrivateSymbol(),
786 };
787
788 std::vector<Handle<JSObject>> objects;
789
790 {
791 Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
792 Handle<JSObject> object = factory->NewJSObject(function);
793 AddProperties(object, names, arraysize(names));
794 CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
795 CHECK(!object->map()->is_dictionary_map());
796 objects.push_back(object);
797 }
798
799 {
800 Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
801 Handle<JSObject> object = factory->NewJSObject(function);
802 AddProperties(object, names, arraysize(names));
803 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, "test");
804 CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
805 CHECK(object->map()->is_dictionary_map());
806 objects.push_back(object);
807 }
808
809 {
810 Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
811 JSFunction::EnsureHasInitialMap(function);
812 function->initial_map()->set_instance_type(JS_GLOBAL_OBJECT_TYPE);
813 function->initial_map()->set_is_prototype_map(true);
814 function->initial_map()->set_dictionary_map(true);
815 Handle<JSObject> object = factory->NewJSGlobalObject(function);
816 AddProperties(object, names, arraysize(names));
817 CHECK_EQ(JS_GLOBAL_OBJECT_TYPE, object->map()->instance_type());
818 CHECK(object->map()->is_dictionary_map());
819 objects.push_back(object);
820 }
821
822 {
823 for (Handle<JSObject> object : objects) {
824 for (size_t name_index = 0; name_index < arraysize(names); name_index++) {
825 Handle<Name> name = names[name_index];
826 CHECK(JSReceiver::HasProperty(object, name).FromJust());
827 ft.CheckTrue(object, name, expect_found);
828 }
829 }
830 }
831
832 {
833 Handle<Name> non_existing_names[] = {
834 factory->InternalizeUtf8String("ne_a"),
835 factory->InternalizeUtf8String("ne_bb"),
836 factory->InternalizeUtf8String("ne_ccc"),
837 factory->InternalizeUtf8String("ne_dddd"),
838 };
839 for (Handle<JSObject> object : objects) {
840 for (size_t key_index = 0; key_index < arraysize(non_existing_names);
841 key_index++) {
842 Handle<Name> key = non_existing_names[key_index];
843 CHECK(!JSReceiver::HasProperty(object, key).FromJust());
844 ft.CheckTrue(object, key, expect_not_found);
845 }
846 }
847 }
848
849 {
850 Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
851 Handle<JSProxy> object = factory->NewJSProxy(function, objects[0]);
852 CHECK_EQ(JS_PROXY_TYPE, object->map()->instance_type());
853 ft.CheckTrue(object, names[0], expect_bailout);
854 }
855
856 {
857 Handle<JSObject> object = isolate->global_proxy();
858 CHECK_EQ(JS_GLOBAL_PROXY_TYPE, object->map()->instance_type());
859 ft.CheckTrue(object, names[0], expect_bailout);
860 }
861 }
862
863 namespace {
864
865 void AddElement(Handle<JSObject> object, uint32_t index, Handle<Object> value,
866 PropertyAttributes attributes = NONE) {
867 JSObject::AddDataElement(object, index, value, attributes).ToHandleChecked();
868 }
869
870 } // namespace
871
872 TEST(TryLookupElement) {
873 typedef CodeStubAssembler::Label Label;
874 Isolate* isolate(CcTest::InitIsolateOnce());
875
876 const int param_count = 4;
877 CodeStubAssemblerTester m(isolate, param_count);
878
879 enum Result { kFound, kNotFound, kBailout };
880 {
881 Node* object = m.Parameter(0);
882 Node* index = m.SmiToWord32(m.Parameter(1));
883 Node* expected_result = m.Parameter(2);
884
885 Label passed(&m), failed(&m);
886 Label if_found(&m), if_not_found(&m), if_bailout(&m);
887
888 Node* map = m.LoadMap(object);
889 Node* instance_type = m.LoadMapInstanceType(map);
890
891 m.TryLookupElement(object, map, instance_type, index, &if_found,
892 &if_not_found, &if_bailout);
893
894 m.Bind(&if_found);
895 m.Branch(m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
896 &passed, &failed);
897
898 m.Bind(&if_not_found);
899 m.Branch(
900 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
901 &passed, &failed);
902
903 m.Bind(&if_bailout);
904 m.Branch(
905 m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kBailout))),
906 &passed, &failed);
907
908 m.Bind(&passed);
909 m.Return(m.BooleanConstant(true));
910
911 m.Bind(&failed);
912 m.Return(m.BooleanConstant(false));
913 }
914
915 Handle<Code> code = m.GenerateCode();
916 FunctionTester ft(code, param_count);
917
918 Factory* factory = isolate->factory();
919 Handle<Object> smi0(Smi::FromInt(0), isolate);
920 Handle<Object> smi1(Smi::FromInt(1), isolate);
921 Handle<Object> smi7(Smi::FromInt(7), isolate);
922 Handle<Object> smi13(Smi::FromInt(13), isolate);
923 Handle<Object> smi42(Smi::FromInt(42), isolate);
924
925 Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
926 Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
927 Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate);
928
929 #define CHECK_FOUND(object, index) \
930 CHECK(JSReceiver::HasElement(object, index).FromJust()); \
931 ft.CheckTrue(object, smi##index, expect_found);
932
933 #define CHECK_NOT_FOUND(object, index) \
934 CHECK(!JSReceiver::HasElement(object, index).FromJust()); \
935 ft.CheckTrue(object, smi##index, expect_not_found);
936
937 {
938 Handle<JSArray> object = factory->NewJSArray(0, FAST_SMI_ELEMENTS);
939 AddElement(object, 0, smi0);
940 AddElement(object, 1, smi0);
941 CHECK_EQ(FAST_SMI_ELEMENTS, object->map()->elements_kind());
942
943 CHECK_FOUND(object, 0);
944 CHECK_FOUND(object, 1);
945 CHECK_NOT_FOUND(object, 7);
946 CHECK_NOT_FOUND(object, 13);
947 CHECK_NOT_FOUND(object, 42);
948 }
949
950 {
951 Handle<JSArray> object = factory->NewJSArray(0, FAST_HOLEY_SMI_ELEMENTS);
952 AddElement(object, 0, smi0);
953 AddElement(object, 13, smi0);
954 CHECK_EQ(FAST_HOLEY_SMI_ELEMENTS, object->map()->elements_kind());
955
956 CHECK_FOUND(object, 0);
957 CHECK_NOT_FOUND(object, 1);
958 CHECK_NOT_FOUND(object, 7);
959 CHECK_FOUND(object, 13);
960 CHECK_NOT_FOUND(object, 42);
961 }
962
963 {
964 Handle<JSArray> object = factory->NewJSArray(0, FAST_ELEMENTS);
965 AddElement(object, 0, smi0);
966 AddElement(object, 1, smi0);
967 CHECK_EQ(FAST_ELEMENTS, object->map()->elements_kind());
968
969 CHECK_FOUND(object, 0);
970 CHECK_FOUND(object, 1);
971 CHECK_NOT_FOUND(object, 7);
972 CHECK_NOT_FOUND(object, 13);
973 CHECK_NOT_FOUND(object, 42);
974 }
975
976 {
977 Handle<JSArray> object = factory->NewJSArray(0, FAST_HOLEY_ELEMENTS);
978 AddElement(object, 0, smi0);
979 AddElement(object, 13, smi0);
980 CHECK_EQ(FAST_HOLEY_ELEMENTS, object->map()->elements_kind());
981
982 CHECK_FOUND(object, 0);
983 CHECK_NOT_FOUND(object, 1);
984 CHECK_NOT_FOUND(object, 7);
985 CHECK_FOUND(object, 13);
986 CHECK_NOT_FOUND(object, 42);
987 }
988
989 {
990 Handle<JSFunction> constructor = isolate->string_function();
991 Handle<JSObject> object = factory->NewJSObject(constructor);
992 Handle<String> str = factory->InternalizeUtf8String("ab");
993 Handle<JSValue>::cast(object)->set_value(*str);
994 AddElement(object, 13, smi0);
995 CHECK_EQ(FAST_STRING_WRAPPER_ELEMENTS, object->map()->elements_kind());
996
997 CHECK_FOUND(object, 0);
998 CHECK_FOUND(object, 1);
999 CHECK_NOT_FOUND(object, 7);
1000 CHECK_FOUND(object, 13);
1001 CHECK_NOT_FOUND(object, 42);
1002 }
1003
1004 {
1005 Handle<JSFunction> constructor = isolate->string_function();
1006 Handle<JSObject> object = factory->NewJSObject(constructor);
1007 Handle<String> str = factory->InternalizeUtf8String("ab");
1008 Handle<JSValue>::cast(object)->set_value(*str);
1009 AddElement(object, 13, smi0);
1010 JSObject::NormalizeElements(object);
1011 CHECK_EQ(SLOW_STRING_WRAPPER_ELEMENTS, object->map()->elements_kind());
1012
1013 CHECK_FOUND(object, 0);
1014 CHECK_FOUND(object, 1);
1015 CHECK_NOT_FOUND(object, 7);
1016 CHECK_FOUND(object, 13);
1017 CHECK_NOT_FOUND(object, 42);
1018 }
1019
1020 // TODO(ishell): uncomment once NO_ELEMENTS kind is supported.
1021 // {
1022 // Handle<Map> map = Map::Create(isolate, 0);
1023 // map->set_elements_kind(NO_ELEMENTS);
1024 // Handle<JSObject> object = factory->NewJSObjectFromMap(map);
1025 // CHECK_EQ(NO_ELEMENTS, object->map()->elements_kind());
1026 //
1027 // CHECK_NOT_FOUND(object, 0);
1028 // CHECK_NOT_FOUND(object, 1);
1029 // CHECK_NOT_FOUND(object, 7);
1030 // CHECK_NOT_FOUND(object, 13);
1031 // CHECK_NOT_FOUND(object, 42);
1032 // }
1033
1034 #undef CHECK_FOUND
1035 #undef CHECK_NOT_FOUND
1036
1037 {
1038 Handle<JSArray> handler = factory->NewJSArray(0);
1039 Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
1040 Handle<JSProxy> object = factory->NewJSProxy(function, handler);
1041 CHECK_EQ(JS_PROXY_TYPE, object->map()->instance_type());
1042 ft.CheckTrue(object, smi0, expect_bailout);
1043 }
1044
1045 {
1046 Handle<JSObject> object = isolate->global_object();
1047 CHECK_EQ(JS_GLOBAL_OBJECT_TYPE, object->map()->instance_type());
1048 ft.CheckTrue(object, smi0, expect_bailout);
1049 }
1050
1051 {
1052 Handle<JSObject> object = isolate->global_proxy();
1053 CHECK_EQ(JS_GLOBAL_PROXY_TYPE, object->map()->instance_type());
1054 ft.CheckTrue(object, smi0, expect_bailout);
1055 }
1056 }
1057
1058 } // namespace internal
1059 } // namespace v8
OLDNEW
« no previous file with comments | « test/cctest/compiler/test-code-stub-assembler.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698