OLD | NEW |
---|---|
(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 | |
Igor Sheludko
2016/05/30 12:11:34
New tests are below.
| |
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 | |
OLD | NEW |