Line data Source code
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 <cmath>
6 :
7 : #include "src/api-inl.h"
8 : #include "src/base/utils/random-number-generator.h"
9 : #include "src/builtins/builtins-promise-gen.h"
10 : #include "src/builtins/builtins-promise.h"
11 : #include "src/builtins/builtins-string-gen.h"
12 : #include "src/char-predicates.h"
13 : #include "src/code-factory.h"
14 : #include "src/code-stub-assembler.h"
15 : #include "src/compiler/node.h"
16 : #include "src/debug/debug.h"
17 : #include "src/heap/heap-inl.h"
18 : #include "src/isolate.h"
19 : #include "src/objects-inl.h"
20 : #include "src/objects/hash-table-inl.h"
21 : #include "src/objects/heap-number-inl.h"
22 : #include "src/objects/js-array-buffer-inl.h"
23 : #include "src/objects/js-array-inl.h"
24 : #include "src/objects/promise-inl.h"
25 : #include "src/objects/smi.h"
26 : #include "src/objects/struct-inl.h"
27 : #include "test/cctest/compiler/code-assembler-tester.h"
28 : #include "test/cctest/compiler/function-tester.h"
29 :
30 : namespace v8 {
31 : namespace internal {
32 : namespace compiler {
33 :
34 : namespace {
35 :
36 : using Label = CodeAssemblerLabel;
37 : using Variable = CodeAssemblerVariable;
38 : template <class T>
39 : using TVariable = TypedCodeAssemblerVariable<T>;
40 :
41 : Handle<String> MakeString(const char* str) {
42 : Isolate* isolate = CcTest::i_isolate();
43 : Factory* factory = isolate->factory();
44 1370 : return factory->InternalizeUtf8String(str);
45 : }
46 :
47 1350 : Handle<String> MakeName(const char* str, int suffix) {
48 : EmbeddedVector<char, 128> buffer;
49 1350 : SNPrintF(buffer, "%s%d", str, suffix);
50 2700 : return MakeString(buffer.start());
51 : }
52 :
53 5 : int sum9(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
54 : int a8) {
55 5 : return a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;
56 : }
57 :
58 5 : static int sum3(int a0, int a1, int a2) { return a0 + a1 + a2; }
59 :
60 : } // namespace
61 :
62 28342 : TEST(CallCFunction9) {
63 5 : Isolate* isolate(CcTest::InitIsolateOnce());
64 :
65 : const int kNumParams = 0;
66 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
67 5 : CodeStubAssembler m(asm_tester.state());
68 :
69 : {
70 : Node* const fun_constant = m.ExternalConstant(
71 10 : ExternalReference::Create(reinterpret_cast<Address>(sum9)));
72 :
73 5 : MachineType type_intptr = MachineType::IntPtr();
74 :
75 : Node* const result = m.CallCFunction9(
76 : type_intptr, type_intptr, type_intptr, type_intptr, type_intptr,
77 : type_intptr, type_intptr, type_intptr, type_intptr, type_intptr,
78 : fun_constant, m.IntPtrConstant(0), m.IntPtrConstant(1),
79 : m.IntPtrConstant(2), m.IntPtrConstant(3), m.IntPtrConstant(4),
80 : m.IntPtrConstant(5), m.IntPtrConstant(6), m.IntPtrConstant(7),
81 50 : m.IntPtrConstant(8));
82 10 : m.Return(m.SmiTag(result));
83 : }
84 :
85 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
86 :
87 10 : Handle<Object> result = ft.Call().ToHandleChecked();
88 15 : CHECK_EQ(36, Handle<Smi>::cast(result)->value());
89 5 : }
90 :
91 28342 : TEST(CallCFunction3WithCallerSavedRegisters) {
92 5 : Isolate* isolate(CcTest::InitIsolateOnce());
93 :
94 : const int kNumParams = 0;
95 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
96 5 : CodeStubAssembler m(asm_tester.state());
97 :
98 : {
99 : Node* const fun_constant = m.ExternalConstant(
100 10 : ExternalReference::Create(reinterpret_cast<Address>(sum3)));
101 :
102 5 : MachineType type_intptr = MachineType::IntPtr();
103 :
104 : Node* const result = m.CallCFunction3WithCallerSavedRegisters(
105 : type_intptr, type_intptr, type_intptr, type_intptr, fun_constant,
106 : m.IntPtrConstant(0), m.IntPtrConstant(1), m.IntPtrConstant(2),
107 20 : kSaveFPRegs);
108 10 : m.Return(m.SmiTag(result));
109 : }
110 :
111 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
112 :
113 10 : Handle<Object> result = ft.Call().ToHandleChecked();
114 15 : CHECK_EQ(3, Handle<Smi>::cast(result)->value());
115 5 : }
116 :
117 : namespace {
118 :
119 205 : void CheckToUint32Result(uint32_t expected, Handle<Object> result) {
120 205 : const int64_t result_int64 = NumberToInt64(*result);
121 205 : const uint32_t result_uint32 = NumberToUint32(*result);
122 :
123 205 : CHECK_EQ(static_cast<int64_t>(result_uint32), result_int64);
124 205 : CHECK_EQ(expected, result_uint32);
125 :
126 : // Ensure that the result is normalized to a Smi, i.e. a HeapNumber is only
127 : // returned if the result is not within Smi range.
128 : const bool expected_fits_into_intptr =
129 : static_cast<int64_t>(expected) <=
130 : static_cast<int64_t>(std::numeric_limits<intptr_t>::max());
131 205 : if (expected_fits_into_intptr &&
132 205 : Smi::IsValid(static_cast<intptr_t>(expected))) {
133 320 : CHECK(result->IsSmi());
134 : } else {
135 90 : CHECK(result->IsHeapNumber());
136 : }
137 205 : }
138 :
139 : } // namespace
140 :
141 28342 : TEST(ToUint32) {
142 5 : Isolate* isolate(CcTest::InitIsolateOnce());
143 : Factory* factory = isolate->factory();
144 :
145 : const int kNumParams = 1;
146 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
147 5 : CodeStubAssembler m(asm_tester.state());
148 :
149 : const int kContextOffset = 2;
150 5 : Node* const context = m.Parameter(kNumParams + kContextOffset);
151 5 : Node* const input = m.Parameter(0);
152 10 : m.Return(m.ToUint32(context, input));
153 :
154 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
155 :
156 : // clang-format off
157 : double inputs[] = {
158 : std::nan("-1"), std::nan("1"), std::nan("2"),
159 : -std::numeric_limits<double>::infinity(),
160 : std::numeric_limits<double>::infinity(),
161 : -0.0, -0.001, -0.5, -0.999, -1.0,
162 : 0.0, 0.001, 0.5, 0.999, 1.0,
163 : -2147483647.9, -2147483648.0, -2147483648.5, -2147483648.9, // SmiMin.
164 : 2147483646.9, 2147483647.0, 2147483647.5, 2147483647.9, // SmiMax.
165 : -4294967295.9, -4294967296.0, -4294967296.5, -4294967297.0, // - 2^32.
166 : 4294967295.9, 4294967296.0, 4294967296.5, 4294967297.0, // 2^32.
167 5 : };
168 :
169 : uint32_t expectations[] = {
170 : 0, 0, 0,
171 : 0,
172 : 0,
173 : 0, 0, 0, 0, 4294967295,
174 : 0, 0, 0, 0, 1,
175 : 2147483649, 2147483648, 2147483648, 2147483648,
176 : 2147483646, 2147483647, 2147483647, 2147483647,
177 : 1, 0, 0, 4294967295,
178 : 4294967295, 0, 0, 1,
179 5 : };
180 : // clang-format on
181 :
182 : STATIC_ASSERT(arraysize(inputs) == arraysize(expectations));
183 :
184 : const int test_count = arraysize(inputs);
185 160 : for (int i = 0; i < test_count; i++) {
186 155 : Handle<Object> input_obj = factory->NewNumber(inputs[i]);
187 : Handle<HeapNumber> input_num;
188 :
189 : // Check with Smi input.
190 310 : if (input_obj->IsSmi()) {
191 25 : Handle<Smi> input_smi = Handle<Smi>::cast(input_obj);
192 50 : Handle<Object> result = ft.Call(input_smi).ToHandleChecked();
193 25 : CheckToUint32Result(expectations[i], result);
194 25 : input_num = factory->NewHeapNumber(inputs[i]);
195 : } else {
196 130 : input_num = Handle<HeapNumber>::cast(input_obj);
197 : }
198 :
199 : // Check with HeapNumber input.
200 : {
201 310 : CHECK(input_num->IsHeapNumber());
202 310 : Handle<Object> result = ft.Call(input_num).ToHandleChecked();
203 155 : CheckToUint32Result(expectations[i], result);
204 : }
205 : }
206 :
207 : // A couple of final cases for ToNumber conversions.
208 10 : CheckToUint32Result(0, ft.Call(factory->undefined_value()).ToHandleChecked());
209 10 : CheckToUint32Result(0, ft.Call(factory->null_value()).ToHandleChecked());
210 10 : CheckToUint32Result(0, ft.Call(factory->false_value()).ToHandleChecked());
211 10 : CheckToUint32Result(1, ft.Call(factory->true_value()).ToHandleChecked());
212 : CheckToUint32Result(
213 : 42,
214 10 : ft.Call(factory->NewStringFromAsciiChecked("0x2A")).ToHandleChecked());
215 :
216 10 : ft.CheckThrows(factory->match_symbol());
217 5 : }
218 :
219 : namespace {
220 55 : void IsValidPositiveSmiCase(Isolate* isolate, intptr_t value) {
221 : const int kNumParams = 0;
222 55 : CodeAssemblerTester asm_tester(isolate, kNumParams);
223 :
224 55 : CodeStubAssembler m(asm_tester.state());
225 : m.Return(
226 165 : m.SelectBooleanConstant(m.IsValidPositiveSmi(m.IntPtrConstant(value))));
227 :
228 55 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
229 55 : MaybeHandle<Object> maybe_handle = ft.Call();
230 :
231 55 : bool expected = i::PlatformSmiTagging::IsValidSmi(value) && (value >= 0);
232 55 : if (expected) {
233 50 : CHECK(maybe_handle.ToHandleChecked()->IsTrue(isolate));
234 : } else {
235 60 : CHECK(maybe_handle.ToHandleChecked()->IsFalse(isolate));
236 55 : }
237 55 : }
238 : } // namespace
239 :
240 28342 : TEST(IsValidPositiveSmi) {
241 5 : Isolate* isolate(CcTest::InitIsolateOnce());
242 :
243 5 : IsValidPositiveSmiCase(isolate, -1);
244 5 : IsValidPositiveSmiCase(isolate, 0);
245 5 : IsValidPositiveSmiCase(isolate, 1);
246 :
247 5 : IsValidPositiveSmiCase(isolate, 0x3FFFFFFFU);
248 5 : IsValidPositiveSmiCase(isolate, 0xC0000000U);
249 5 : IsValidPositiveSmiCase(isolate, 0x40000000U);
250 5 : IsValidPositiveSmiCase(isolate, 0xBFFFFFFFU);
251 :
252 : typedef std::numeric_limits<int32_t> int32_limits;
253 5 : IsValidPositiveSmiCase(isolate, int32_limits::max());
254 5 : IsValidPositiveSmiCase(isolate, int32_limits::min());
255 : #ifdef V8_TARGET_ARCH_64_BIT
256 : IsValidPositiveSmiCase(isolate,
257 5 : static_cast<intptr_t>(int32_limits::max()) + 1);
258 : IsValidPositiveSmiCase(isolate,
259 5 : static_cast<intptr_t>(int32_limits::min()) - 1);
260 : #endif
261 5 : }
262 :
263 28342 : TEST(FixedArrayAccessSmiIndex) {
264 5 : Isolate* isolate(CcTest::InitIsolateOnce());
265 5 : CodeAssemblerTester asm_tester(isolate);
266 5 : CodeStubAssembler m(asm_tester.state());
267 5 : Handle<FixedArray> array = isolate->factory()->NewFixedArray(5);
268 : array->set(4, Smi::FromInt(733));
269 : m.Return(m.LoadFixedArrayElement(m.HeapConstant(array),
270 10 : m.SmiTag(m.IntPtrConstant(4)), 0,
271 15 : CodeStubAssembler::SMI_PARAMETERS));
272 5 : FunctionTester ft(asm_tester.GenerateCode());
273 5 : MaybeHandle<Object> result = ft.Call();
274 15 : CHECK_EQ(733, Handle<Smi>::cast(result.ToHandleChecked())->value());
275 5 : }
276 :
277 28342 : TEST(LoadHeapNumberValue) {
278 5 : Isolate* isolate(CcTest::InitIsolateOnce());
279 5 : CodeAssemblerTester asm_tester(isolate);
280 5 : CodeStubAssembler m(asm_tester.state());
281 5 : Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(1234);
282 : m.Return(m.SmiFromInt32(m.Signed(
283 20 : m.ChangeFloat64ToUint32(m.LoadHeapNumberValue(m.HeapConstant(number))))));
284 5 : FunctionTester ft(asm_tester.GenerateCode());
285 5 : MaybeHandle<Object> result = ft.Call();
286 15 : CHECK_EQ(1234, Handle<Smi>::cast(result.ToHandleChecked())->value());
287 5 : }
288 :
289 28342 : TEST(LoadInstanceType) {
290 5 : Isolate* isolate(CcTest::InitIsolateOnce());
291 5 : CodeAssemblerTester asm_tester(isolate);
292 5 : CodeStubAssembler m(asm_tester.state());
293 : Handle<HeapObject> undefined = isolate->factory()->undefined_value();
294 15 : m.Return(m.SmiFromInt32(m.LoadInstanceType(m.HeapConstant(undefined))));
295 5 : FunctionTester ft(asm_tester.GenerateCode());
296 5 : MaybeHandle<Object> result = ft.Call();
297 10 : CHECK_EQ(InstanceType::ODDBALL_TYPE,
298 5 : Handle<Smi>::cast(result.ToHandleChecked())->value());
299 5 : }
300 :
301 28342 : TEST(DecodeWordFromWord32) {
302 5 : Isolate* isolate(CcTest::InitIsolateOnce());
303 5 : CodeAssemblerTester asm_tester(isolate);
304 5 : CodeStubAssembler m(asm_tester.state());
305 :
306 : class TestBitField : public BitField<unsigned, 3, 3> {};
307 : m.Return(m.SmiTag(
308 20 : m.Signed(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2F)))));
309 5 : FunctionTester ft(asm_tester.GenerateCode());
310 5 : MaybeHandle<Object> result = ft.Call();
311 : // value = 00101111
312 : // mask = 00111000
313 : // result = 101
314 15 : CHECK_EQ(5, Handle<Smi>::cast(result.ToHandleChecked())->value());
315 5 : }
316 :
317 28342 : TEST(JSFunction) {
318 : const int kNumParams = 3; // Receiver, left, right.
319 5 : Isolate* isolate(CcTest::InitIsolateOnce());
320 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
321 5 : CodeStubAssembler m(asm_tester.state());
322 : m.Return(m.SmiFromInt32(
323 25 : m.Int32Add(m.SmiToInt32(m.Parameter(1)), m.SmiToInt32(m.Parameter(2)))));
324 :
325 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
326 :
327 : MaybeHandle<Object> result = ft.Call(isolate->factory()->undefined_value(),
328 : handle(Smi::FromInt(23), isolate),
329 5 : handle(Smi::FromInt(34), isolate));
330 15 : CHECK_EQ(57, Handle<Smi>::cast(result.ToHandleChecked())->value());
331 5 : }
332 :
333 28342 : TEST(ComputeIntegerHash) {
334 5 : Isolate* isolate(CcTest::InitIsolateOnce());
335 : const int kNumParams = 1;
336 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
337 5 : CodeStubAssembler m(asm_tester.state());
338 :
339 25 : m.Return(m.SmiFromInt32(m.ComputeSeededHash(m.SmiUntag(m.Parameter(0)))));
340 :
341 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
342 :
343 5 : base::RandomNumberGenerator rand_gen(FLAG_random_seed);
344 :
345 5125 : for (int i = 0; i < 1024; i++) {
346 5120 : int k = rand_gen.NextInt(Smi::kMaxValue);
347 :
348 : Handle<Smi> key(Smi::FromInt(k), isolate);
349 10240 : Handle<Object> result = ft.Call(key).ToHandleChecked();
350 :
351 5120 : uint32_t hash = ComputeSeededHash(k, isolate->heap()->HashSeed());
352 10240 : Smi expected = Smi::FromInt(hash);
353 10240 : CHECK_EQ(expected, Smi::cast(*result));
354 5 : }
355 5 : }
356 :
357 28342 : TEST(ToString) {
358 5 : Isolate* isolate(CcTest::InitIsolateOnce());
359 : const int kNumParams = 1;
360 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
361 5 : CodeStubAssembler m(asm_tester.state());
362 20 : m.Return(m.ToString(m.Parameter(kNumParams + 2), m.Parameter(0)));
363 :
364 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
365 :
366 5 : Handle<FixedArray> test_cases = isolate->factory()->NewFixedArray(5);
367 5 : Handle<FixedArray> smi_test = isolate->factory()->NewFixedArray(2);
368 : smi_test->set(0, Smi::FromInt(42));
369 5 : Handle<String> str(isolate->factory()->InternalizeUtf8String("42"));
370 10 : smi_test->set(1, *str);
371 10 : test_cases->set(0, *smi_test);
372 :
373 5 : Handle<FixedArray> number_test = isolate->factory()->NewFixedArray(2);
374 5 : Handle<HeapNumber> num(isolate->factory()->NewHeapNumber(3.14));
375 10 : number_test->set(0, *num);
376 5 : str = isolate->factory()->InternalizeUtf8String("3.14");
377 10 : number_test->set(1, *str);
378 10 : test_cases->set(1, *number_test);
379 :
380 5 : Handle<FixedArray> string_test = isolate->factory()->NewFixedArray(2);
381 5 : str = isolate->factory()->InternalizeUtf8String("test");
382 10 : string_test->set(0, *str);
383 10 : string_test->set(1, *str);
384 10 : test_cases->set(2, *string_test);
385 :
386 5 : Handle<FixedArray> oddball_test = isolate->factory()->NewFixedArray(2);
387 10 : oddball_test->set(0, ReadOnlyRoots(isolate).undefined_value());
388 5 : str = isolate->factory()->InternalizeUtf8String("undefined");
389 10 : oddball_test->set(1, *str);
390 10 : test_cases->set(3, *oddball_test);
391 :
392 5 : Handle<FixedArray> tostring_test = isolate->factory()->NewFixedArray(2);
393 5 : Handle<FixedArray> js_array_storage = isolate->factory()->NewFixedArray(2);
394 : js_array_storage->set(0, Smi::FromInt(1));
395 : js_array_storage->set(1, Smi::FromInt(2));
396 5 : Handle<JSArray> js_array = isolate->factory()->NewJSArray(2);
397 5 : JSArray::SetContent(js_array, js_array_storage);
398 10 : tostring_test->set(0, *js_array);
399 5 : str = isolate->factory()->InternalizeUtf8String("1,2");
400 10 : tostring_test->set(1, *str);
401 10 : test_cases->set(4, *tostring_test);
402 :
403 30 : for (int i = 0; i < 5; ++i) {
404 : Handle<FixedArray> test =
405 : handle(FixedArray::cast(test_cases->get(i)), isolate);
406 25 : Handle<Object> obj = handle(test->get(0), isolate);
407 25 : Handle<String> expected = handle(String::cast(test->get(1)), isolate);
408 50 : Handle<Object> result = ft.Call(obj).ToHandleChecked();
409 50 : CHECK(result->IsString());
410 25 : CHECK(String::Equals(isolate, Handle<String>::cast(result), expected));
411 5 : }
412 5 : }
413 :
414 28342 : TEST(TryToName) {
415 5 : Isolate* isolate(CcTest::InitIsolateOnce());
416 :
417 : const int kNumParams = 3;
418 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
419 5 : CodeStubAssembler m(asm_tester.state());
420 :
421 : enum Result { kKeyIsIndex, kKeyIsUnique, kBailout };
422 : {
423 5 : Node* key = m.Parameter(0);
424 5 : Node* expected_result = m.Parameter(1);
425 5 : Node* expected_arg = m.Parameter(2);
426 :
427 5 : Label passed(&m), failed(&m);
428 5 : Label if_keyisindex(&m), if_keyisunique(&m), if_bailout(&m);
429 : {
430 5 : Variable var_index(&m, MachineType::PointerRepresentation());
431 10 : Variable var_unique(&m, MachineRepresentation::kTagged);
432 :
433 : m.TryToName(key, &if_keyisindex, &var_index, &if_keyisunique, &var_unique,
434 5 : &if_bailout);
435 :
436 5 : m.BIND(&if_keyisindex);
437 : m.GotoIfNot(m.WordEqual(expected_result,
438 10 : m.SmiConstant(Smi::FromInt(kKeyIsIndex))),
439 5 : &failed);
440 15 : m.Branch(m.WordEqual(m.SmiUntag(expected_arg), var_index.value()),
441 10 : &passed, &failed);
442 :
443 5 : m.BIND(&if_keyisunique);
444 : m.GotoIfNot(m.WordEqual(expected_result,
445 10 : m.SmiConstant(Smi::FromInt(kKeyIsUnique))),
446 5 : &failed);
447 20 : m.Branch(m.WordEqual(expected_arg, var_unique.value()), &passed, &failed);
448 : }
449 :
450 5 : m.BIND(&if_bailout);
451 : m.Branch(
452 10 : m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kBailout))),
453 5 : &passed, &failed);
454 :
455 5 : m.BIND(&passed);
456 10 : m.Return(m.BooleanConstant(true));
457 :
458 5 : m.BIND(&failed);
459 15 : m.Return(m.BooleanConstant(false));
460 : }
461 :
462 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
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::kZero, isolate);
471 5 : 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 5 : ft.CheckTrue(key, expect_index, key);
478 : }
479 :
480 : {
481 : // TryToName(<negative smi>) => if_keyisindex: smi value.
482 : // A subsequent bounds check needs to take care of this case.
483 : Handle<Object> key(Smi::FromInt(-1), isolate);
484 5 : ft.CheckTrue(key, expect_index, key);
485 : }
486 :
487 : {
488 : // TryToName(<heap number with int value>) => if_keyisindex: number.
489 5 : Handle<Object> key(isolate->factory()->NewHeapNumber(153));
490 : Handle<Object> index(Smi::FromInt(153), isolate);
491 5 : ft.CheckTrue(key, expect_index, index);
492 : }
493 :
494 : {
495 : // TryToName(<true>) => if_keyisunique: "true".
496 : Handle<Object> key = isolate->factory()->true_value();
497 5 : Handle<Object> unique = isolate->factory()->InternalizeUtf8String("true");
498 5 : ft.CheckTrue(key, expect_unique, unique);
499 : }
500 :
501 : {
502 : // TryToName(<false>) => if_keyisunique: "false".
503 : Handle<Object> key = isolate->factory()->false_value();
504 5 : Handle<Object> unique = isolate->factory()->InternalizeUtf8String("false");
505 5 : ft.CheckTrue(key, expect_unique, unique);
506 : }
507 :
508 : {
509 : // TryToName(<null>) => if_keyisunique: "null".
510 : Handle<Object> key = isolate->factory()->null_value();
511 5 : Handle<Object> unique = isolate->factory()->InternalizeUtf8String("null");
512 5 : ft.CheckTrue(key, expect_unique, unique);
513 : }
514 :
515 : {
516 : // TryToName(<undefined>) => if_keyisunique: "undefined".
517 : Handle<Object> key = isolate->factory()->undefined_value();
518 : Handle<Object> unique =
519 5 : isolate->factory()->InternalizeUtf8String("undefined");
520 5 : ft.CheckTrue(key, expect_unique, unique);
521 : }
522 :
523 : {
524 : // TryToName(<symbol>) => if_keyisunique: <symbol>.
525 5 : Handle<Object> key = isolate->factory()->NewSymbol();
526 5 : ft.CheckTrue(key, expect_unique, key);
527 : }
528 :
529 : {
530 : // TryToName(<internalized string>) => if_keyisunique: <internalized string>
531 5 : Handle<Object> key = isolate->factory()->InternalizeUtf8String("test");
532 5 : ft.CheckTrue(key, expect_unique, key);
533 : }
534 :
535 : {
536 : // TryToName(<internalized number string>) => if_keyisindex: number.
537 5 : Handle<Object> key = isolate->factory()->InternalizeUtf8String("153");
538 : Handle<Object> index(Smi::FromInt(153), isolate);
539 5 : ft.CheckTrue(key, expect_index, index);
540 : }
541 :
542 : {
543 : // TryToName(<internalized uncacheable number string>) => bailout
544 : Handle<Object> key =
545 5 : isolate->factory()->InternalizeUtf8String("4294967294");
546 5 : ft.CheckTrue(key, expect_bailout);
547 : }
548 :
549 : {
550 : // TryToName(<non-internalized number string>) => if_keyisindex: number.
551 5 : Handle<String> key = isolate->factory()->NewStringFromAsciiChecked("153");
552 : uint32_t dummy;
553 5 : CHECK(key->AsArrayIndex(&dummy));
554 5 : CHECK(key->HasHashCode());
555 10 : CHECK(!key->IsInternalizedString());
556 : Handle<Object> index(Smi::FromInt(153), isolate);
557 5 : ft.CheckTrue(key, expect_index, index);
558 : }
559 :
560 : {
561 : // TryToName(<number string without cached index>) => bailout.
562 5 : Handle<String> key = isolate->factory()->NewStringFromAsciiChecked("153");
563 5 : CHECK(!key->HasHashCode());
564 5 : ft.CheckTrue(key, expect_bailout);
565 : }
566 :
567 : {
568 : // TryToName(<non-internalized string>) => bailout.
569 5 : Handle<Object> key = isolate->factory()->NewStringFromAsciiChecked("test");
570 5 : ft.CheckTrue(key, expect_bailout);
571 : }
572 :
573 5 : if (FLAG_thin_strings) {
574 : // TryToName(<thin string>) => internalized version.
575 5 : Handle<String> s = isolate->factory()->NewStringFromAsciiChecked("foo");
576 5 : Handle<String> internalized = isolate->factory()->InternalizeString(s);
577 5 : ft.CheckTrue(s, expect_unique, internalized);
578 : }
579 :
580 5 : if (FLAG_thin_strings) {
581 : // TryToName(<thin two-byte string>) => internalized version.
582 5 : uc16 array1[] = {2001, 2002, 2003};
583 : Vector<const uc16> str1(array1);
584 : Handle<String> s =
585 10 : isolate->factory()->NewStringFromTwoByte(str1).ToHandleChecked();
586 5 : Handle<String> internalized = isolate->factory()->InternalizeString(s);
587 5 : ft.CheckTrue(s, expect_unique, internalized);
588 5 : }
589 5 : }
590 :
591 : namespace {
592 :
593 : template <typename Dictionary>
594 10 : void TestEntryToIndex() {
595 10 : Isolate* isolate(CcTest::InitIsolateOnce());
596 :
597 : const int kNumParams = 1;
598 10 : CodeAssemblerTester asm_tester(isolate, kNumParams);
599 10 : CodeStubAssembler m(asm_tester.state());
600 : {
601 20 : TNode<IntPtrT> entry = m.SmiUntag(m.Parameter(0));
602 : TNode<IntPtrT> result = m.EntryToIndex<Dictionary>(entry);
603 20 : m.Return(m.SmiTag(result));
604 : }
605 :
606 10 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
607 :
608 : // Test a wide range of entries but staying linear in the first 100 entries.
609 14215 : for (int entry = 0; entry < Dictionary::kMaxCapacity;
610 : entry = entry * 1.01 + 1) {
611 : Handle<Object> result =
612 28410 : ft.Call(handle(Smi::FromInt(entry), isolate)).ToHandleChecked();
613 28410 : CHECK_EQ(Dictionary::EntryToIndex(entry), Smi::ToInt(*result));
614 10 : }
615 10 : }
616 :
617 28342 : TEST(NameDictionaryEntryToIndex) { TestEntryToIndex<NameDictionary>(); }
618 28342 : TEST(GlobalDictionaryEntryToIndex) { TestEntryToIndex<GlobalDictionary>(); }
619 :
620 : } // namespace
621 :
622 : namespace {
623 :
624 : template <typename Dictionary>
625 10 : void TestNameDictionaryLookup() {
626 10 : Isolate* isolate(CcTest::InitIsolateOnce());
627 :
628 : const int kNumParams = 4;
629 10 : CodeAssemblerTester asm_tester(isolate, kNumParams);
630 10 : CodeStubAssembler m(asm_tester.state());
631 :
632 : enum Result { kFound, kNotFound };
633 : {
634 10 : TNode<Dictionary> dictionary = m.CAST(m.Parameter(0));
635 10 : TNode<Name> unique_name = m.CAST(m.Parameter(1));
636 10 : TNode<Smi> expected_result = m.CAST(m.Parameter(2));
637 10 : TNode<Object> expected_arg = m.CAST(m.Parameter(3));
638 :
639 10 : Label passed(&m), failed(&m);
640 10 : Label if_found(&m), if_not_found(&m);
641 : TVariable<IntPtrT> var_name_index(&m);
642 :
643 10 : m.NameDictionaryLookup<Dictionary>(dictionary, unique_name, &if_found,
644 : &var_name_index, &if_not_found);
645 10 : m.BIND(&if_found);
646 20 : m.GotoIfNot(
647 : m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
648 : &failed);
649 10 : m.Branch(
650 20 : m.WordEqual(m.SmiUntag(m.CAST(expected_arg)), var_name_index.value()),
651 20 : &passed, &failed);
652 :
653 10 : m.BIND(&if_not_found);
654 20 : m.Branch(
655 : m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
656 : &passed, &failed);
657 :
658 10 : m.BIND(&passed);
659 20 : m.Return(m.BooleanConstant(true));
660 :
661 10 : m.BIND(&failed);
662 30 : m.Return(m.BooleanConstant(false));
663 : }
664 :
665 10 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
666 :
667 : Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
668 : Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
669 :
670 10 : Handle<Dictionary> dictionary = Dictionary::New(isolate, 40);
671 10 : PropertyDetails fake_details = PropertyDetails::Empty();
672 :
673 : Factory* factory = isolate->factory();
674 : Handle<Name> keys[] = {
675 : factory->InternalizeUtf8String("0"),
676 : factory->InternalizeUtf8String("42"),
677 : factory->InternalizeUtf8String("-153"),
678 : factory->InternalizeUtf8String("0.0"),
679 : factory->InternalizeUtf8String("4.2"),
680 : factory->InternalizeUtf8String(""),
681 : factory->InternalizeUtf8String("name"),
682 : factory->NewSymbol(),
683 : factory->NewPrivateSymbol(),
684 90 : };
685 :
686 100 : for (size_t i = 0; i < arraysize(keys); i++) {
687 90 : Handle<Object> value = factory->NewPropertyCell(keys[i]);
688 90 : dictionary =
689 : Dictionary::Add(isolate, dictionary, keys[i], value, fake_details);
690 : }
691 :
692 90 : for (size_t i = 0; i < arraysize(keys); i++) {
693 90 : int entry = dictionary->FindEntry(isolate, keys[i]);
694 : int name_index =
695 : Dictionary::EntryToIndex(entry) + Dictionary::kEntryKeyIndex;
696 90 : CHECK_NE(Dictionary::kNotFound, entry);
697 :
698 : Handle<Object> expected_name_index(Smi::FromInt(name_index), isolate);
699 90 : ft.CheckTrue(dictionary, keys[i], expect_found, expected_name_index);
700 : }
701 :
702 : Handle<Name> non_existing_keys[] = {
703 : factory->InternalizeUtf8String("1"),
704 : factory->InternalizeUtf8String("-42"),
705 : factory->InternalizeUtf8String("153"),
706 : factory->InternalizeUtf8String("-1.0"),
707 : factory->InternalizeUtf8String("1.3"),
708 : factory->InternalizeUtf8String("a"),
709 : factory->InternalizeUtf8String("boom"),
710 : factory->NewSymbol(),
711 : factory->NewPrivateSymbol(),
712 90 : };
713 :
714 100 : for (size_t i = 0; i < arraysize(non_existing_keys); i++) {
715 90 : int entry = dictionary->FindEntry(isolate, non_existing_keys[i]);
716 90 : CHECK_EQ(Dictionary::kNotFound, entry);
717 :
718 90 : ft.CheckTrue(dictionary, non_existing_keys[i], expect_not_found);
719 10 : }
720 10 : }
721 :
722 : } // namespace
723 :
724 28342 : TEST(NameDictionaryLookup) { TestNameDictionaryLookup<NameDictionary>(); }
725 :
726 28342 : TEST(GlobalDictionaryLookup) { TestNameDictionaryLookup<GlobalDictionary>(); }
727 :
728 28342 : TEST(NumberDictionaryLookup) {
729 5 : Isolate* isolate(CcTest::InitIsolateOnce());
730 :
731 : const int kNumParams = 4;
732 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
733 5 : CodeStubAssembler m(asm_tester.state());
734 :
735 : enum Result { kFound, kNotFound };
736 : {
737 5 : TNode<NumberDictionary> dictionary = m.CAST(m.Parameter(0));
738 10 : TNode<IntPtrT> key = m.SmiUntag(m.Parameter(1));
739 5 : TNode<Smi> expected_result = m.CAST(m.Parameter(2));
740 5 : TNode<Object> expected_arg = m.CAST(m.Parameter(3));
741 :
742 5 : Label passed(&m), failed(&m);
743 5 : Label if_found(&m), if_not_found(&m);
744 : TVariable<IntPtrT> var_entry(&m);
745 :
746 : m.NumberDictionaryLookup(dictionary, key, &if_found, &var_entry,
747 5 : &if_not_found);
748 5 : m.BIND(&if_found);
749 : m.GotoIfNot(
750 5 : m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
751 5 : &failed);
752 10 : m.Branch(m.WordEqual(m.SmiUntag(m.CAST(expected_arg)), var_entry.value()),
753 10 : &passed, &failed);
754 :
755 5 : m.BIND(&if_not_found);
756 : m.Branch(
757 5 : m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
758 5 : &passed, &failed);
759 :
760 5 : m.BIND(&passed);
761 10 : m.Return(m.BooleanConstant(true));
762 :
763 5 : m.BIND(&failed);
764 15 : m.Return(m.BooleanConstant(false));
765 : }
766 :
767 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
768 :
769 : Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
770 : Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
771 :
772 : const int kKeysCount = 1000;
773 : Handle<NumberDictionary> dictionary =
774 5 : NumberDictionary::New(isolate, kKeysCount);
775 : uint32_t keys[kKeysCount];
776 :
777 : Handle<Object> fake_value(Smi::FromInt(42), isolate);
778 5 : PropertyDetails fake_details = PropertyDetails::Empty();
779 :
780 5 : base::RandomNumberGenerator rand_gen(FLAG_random_seed);
781 :
782 5005 : for (int i = 0; i < kKeysCount; i++) {
783 5000 : int random_key = rand_gen.NextInt(Smi::kMaxValue);
784 5000 : keys[i] = static_cast<uint32_t>(random_key);
785 5000 : if (dictionary->FindEntry(isolate, keys[i]) != NumberDictionary::kNotFound)
786 : continue;
787 :
788 : dictionary = NumberDictionary::Add(isolate, dictionary, keys[i], fake_value,
789 5000 : fake_details);
790 : }
791 :
792 : // Now try querying existing keys.
793 5000 : for (int i = 0; i < kKeysCount; i++) {
794 10000 : int entry = dictionary->FindEntry(isolate, keys[i]);
795 5000 : CHECK_NE(NumberDictionary::kNotFound, entry);
796 :
797 5000 : Handle<Object> key(Smi::FromInt(keys[i]), isolate);
798 : Handle<Object> expected_entry(Smi::FromInt(entry), isolate);
799 5000 : ft.CheckTrue(dictionary, key, expect_found, expected_entry);
800 : }
801 :
802 : // Now try querying random keys which do not exist in the dictionary.
803 5005 : for (int i = 0; i < kKeysCount;) {
804 5000 : int random_key = rand_gen.NextInt(Smi::kMaxValue);
805 10000 : int entry = dictionary->FindEntry(isolate, random_key);
806 5000 : if (entry != NumberDictionary::kNotFound) continue;
807 5000 : i++;
808 :
809 : Handle<Object> key(Smi::FromInt(random_key), isolate);
810 5000 : ft.CheckTrue(dictionary, key, expect_not_found);
811 5 : }
812 5 : }
813 :
814 28342 : TEST(TransitionLookup) {
815 5 : Isolate* isolate(CcTest::InitIsolateOnce());
816 :
817 : const int kNumParams = 4;
818 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
819 :
820 : enum Result { kFound, kNotFound };
821 :
822 : class TempAssembler : public CodeStubAssembler {
823 : public:
824 : explicit TempAssembler(compiler::CodeAssemblerState* state)
825 5 : : CodeStubAssembler(state) {}
826 :
827 5 : void Generate() {
828 5 : TNode<TransitionArray> transitions = CAST(Parameter(0));
829 5 : TNode<Name> name = CAST(Parameter(1));
830 5 : TNode<Smi> expected_result = CAST(Parameter(2));
831 5 : TNode<Object> expected_arg = CAST(Parameter(3));
832 :
833 5 : Label passed(this), failed(this);
834 5 : Label if_found(this), if_not_found(this);
835 : TVARIABLE(IntPtrT, var_transition_index);
836 :
837 : TransitionLookup(name, transitions, &if_found, &var_transition_index,
838 5 : &if_not_found);
839 :
840 5 : BIND(&if_found);
841 5 : GotoIfNot(WordEqual(expected_result, SmiConstant(kFound)), &failed);
842 10 : Branch(WordEqual(expected_arg, SmiTag(var_transition_index.value())),
843 5 : &passed, &failed);
844 :
845 5 : BIND(&if_not_found);
846 : Branch(WordEqual(expected_result, SmiConstant(kNotFound)), &passed,
847 5 : &failed);
848 :
849 5 : BIND(&passed);
850 10 : Return(BooleanConstant(true));
851 :
852 5 : BIND(&failed);
853 15 : Return(BooleanConstant(false));
854 5 : }
855 : };
856 10 : TempAssembler(asm_tester.state()).Generate();
857 :
858 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
859 :
860 : Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
861 : Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
862 :
863 : const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
864 : STATIC_ASSERT(ATTRS_COUNT == 8);
865 :
866 : const int kKeysCount = 300;
867 5 : Handle<Map> root_map = Map::Create(isolate, 0);
868 1505 : Handle<Name> keys[kKeysCount];
869 :
870 5 : base::RandomNumberGenerator rand_gen(FLAG_random_seed);
871 :
872 : Factory* factory = isolate->factory();
873 5 : Handle<FieldType> any = FieldType::Any(isolate);
874 :
875 1505 : for (int i = 0; i < kKeysCount; i++) {
876 : Handle<Name> name;
877 1500 : if (i % 30 == 0) {
878 50 : name = factory->NewPrivateSymbol();
879 1450 : } else if (i % 10 == 0) {
880 100 : name = factory->NewSymbol();
881 : } else {
882 1350 : int random_key = rand_gen.NextInt(Smi::kMaxValue);
883 1350 : name = MakeName("p", random_key);
884 : }
885 1500 : keys[i] = name;
886 :
887 1500 : bool is_private = name->IsPrivate();
888 1500 : PropertyAttributes base_attributes = is_private ? DONT_ENUM : NONE;
889 :
890 : // Ensure that all the combinations of cases are covered:
891 : // 1) there is a "base" attributes transition
892 : // 2) there are other non-base attributes transitions
893 1500 : if ((i & 1) == 0) {
894 1500 : CHECK(!Map::CopyWithField(isolate, root_map, name, any, base_attributes,
895 : PropertyConstness::kMutable,
896 : Representation::Tagged(), INSERT_TRANSITION)
897 : .is_null());
898 : }
899 :
900 1500 : if ((i & 2) == 0) {
901 6000 : for (int j = 0; j < ATTRS_COUNT; j++) {
902 6000 : PropertyAttributes attributes = static_cast<PropertyAttributes>(j);
903 6000 : if (attributes == base_attributes) continue;
904 : // Don't add private symbols with enumerable attributes.
905 5250 : if (is_private && ((attributes & DONT_ENUM) == 0)) continue;
906 10300 : CHECK(!Map::CopyWithField(isolate, root_map, name, any, attributes,
907 : PropertyConstness::kMutable,
908 : Representation::Tagged(), INSERT_TRANSITION)
909 : .is_null());
910 : }
911 : }
912 : }
913 :
914 10 : CHECK(root_map->raw_transitions()
915 : ->GetHeapObjectAssumeStrong()
916 : ->IsTransitionArray());
917 : Handle<TransitionArray> transitions(
918 : TransitionArray::cast(
919 10 : root_map->raw_transitions()->GetHeapObjectAssumeStrong()),
920 10 : isolate);
921 : DCHECK(transitions->IsSortedNoDuplicates());
922 :
923 : // Ensure we didn't overflow transition array and therefore all the
924 : // combinations of cases are covered.
925 5 : CHECK(TransitionsAccessor(isolate, root_map).CanHaveMoreTransitions());
926 :
927 : // Now try querying keys.
928 : bool positive_lookup_tested = false;
929 : bool negative_lookup_tested = false;
930 1500 : for (int i = 0; i < kKeysCount; i++) {
931 1500 : Handle<Name> name = keys[i];
932 :
933 3000 : int transition_number = transitions->SearchNameForTesting(*name);
934 :
935 1500 : if (transition_number != TransitionArray::kNotFound) {
936 : Handle<Smi> expected_value(
937 : Smi::FromInt(TransitionArray::ToKeyIndex(transition_number)),
938 : isolate);
939 1125 : ft.CheckTrue(transitions, name, expect_found, expected_value);
940 : positive_lookup_tested = true;
941 : } else {
942 375 : ft.CheckTrue(transitions, name, expect_not_found);
943 : negative_lookup_tested = true;
944 : }
945 : }
946 5 : CHECK(positive_lookup_tested);
947 10 : CHECK(negative_lookup_tested);
948 5 : }
949 :
950 : namespace {
951 :
952 25 : void AddProperties(Handle<JSObject> object, Handle<Name> names[],
953 : size_t count) {
954 : Isolate* isolate = object->GetIsolate();
955 250 : for (size_t i = 0; i < count; i++) {
956 225 : Handle<Object> value(Smi::FromInt(static_cast<int>(42 + i)), isolate);
957 225 : JSObject::AddProperty(isolate, object, names[i], value, NONE);
958 : }
959 25 : }
960 :
961 15 : Handle<AccessorPair> CreateAccessorPair(FunctionTester* ft,
962 : const char* getter_body,
963 : const char* setter_body) {
964 15 : Handle<AccessorPair> pair = ft->isolate->factory()->NewAccessorPair();
965 15 : if (getter_body) {
966 30 : pair->set_getter(*ft->NewFunction(getter_body));
967 : }
968 15 : if (setter_body) {
969 30 : pair->set_setter(*ft->NewFunction(setter_body));
970 : }
971 15 : return pair;
972 : }
973 :
974 25 : void AddProperties(Handle<JSObject> object, Handle<Name> names[],
975 : size_t names_count, Handle<Object> values[],
976 : size_t values_count, int seed = 0) {
977 : Isolate* isolate = object->GetIsolate();
978 450 : for (size_t i = 0; i < names_count; i++) {
979 425 : Handle<Object> value = values[(seed + i) % values_count];
980 850 : if (value->IsAccessorPair()) {
981 90 : Handle<AccessorPair> pair = Handle<AccessorPair>::cast(value);
982 180 : Handle<Object> getter(pair->getter(), isolate);
983 180 : Handle<Object> setter(pair->setter(), isolate);
984 180 : JSObject::DefineAccessor(object, names[i], getter, setter, NONE).Check();
985 : } else {
986 335 : JSObject::AddProperty(isolate, object, names[i], value, NONE);
987 : }
988 : }
989 25 : }
990 :
991 : } // namespace
992 :
993 28342 : TEST(TryHasOwnProperty) {
994 5 : Isolate* isolate(CcTest::InitIsolateOnce());
995 :
996 : const int kNumParams = 4;
997 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
998 5 : CodeStubAssembler m(asm_tester.state());
999 :
1000 : enum Result { kFound, kNotFound, kBailout };
1001 : {
1002 5 : Node* object = m.Parameter(0);
1003 5 : Node* unique_name = m.Parameter(1);
1004 5 : Node* expected_result = m.Parameter(2);
1005 :
1006 5 : Label passed(&m), failed(&m);
1007 5 : Label if_found(&m), if_not_found(&m), if_bailout(&m);
1008 :
1009 10 : Node* map = m.LoadMap(object);
1010 10 : Node* instance_type = m.LoadMapInstanceType(map);
1011 :
1012 : m.TryHasOwnProperty(object, map, instance_type, unique_name, &if_found,
1013 5 : &if_not_found, &if_bailout);
1014 :
1015 5 : m.BIND(&if_found);
1016 10 : m.Branch(m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
1017 5 : &passed, &failed);
1018 :
1019 5 : m.BIND(&if_not_found);
1020 : m.Branch(
1021 10 : m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
1022 5 : &passed, &failed);
1023 :
1024 5 : m.BIND(&if_bailout);
1025 : m.Branch(
1026 10 : m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kBailout))),
1027 5 : &passed, &failed);
1028 :
1029 5 : m.BIND(&passed);
1030 10 : m.Return(m.BooleanConstant(true));
1031 :
1032 5 : m.BIND(&failed);
1033 15 : m.Return(m.BooleanConstant(false));
1034 : }
1035 :
1036 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1037 :
1038 : Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
1039 : Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
1040 : Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate);
1041 :
1042 : Factory* factory = isolate->factory();
1043 :
1044 : Handle<Name> deleted_property_name =
1045 5 : factory->InternalizeUtf8String("deleted");
1046 :
1047 : Handle<Name> names[] = {
1048 : factory->InternalizeUtf8String("a"),
1049 : factory->InternalizeUtf8String("bb"),
1050 : factory->InternalizeUtf8String("ccc"),
1051 : factory->InternalizeUtf8String("dddd"),
1052 : factory->InternalizeUtf8String("eeeee"),
1053 : factory->InternalizeUtf8String(""),
1054 : factory->InternalizeUtf8String("name"),
1055 : factory->NewSymbol(),
1056 : factory->NewPrivateSymbol(),
1057 45 : };
1058 :
1059 : std::vector<Handle<JSObject>> objects;
1060 :
1061 : {
1062 : // Fast object, no inobject properties.
1063 : int inobject_properties = 0;
1064 5 : Handle<Map> map = Map::Create(isolate, inobject_properties);
1065 5 : Handle<JSObject> object = factory->NewJSObjectFromMap(map);
1066 5 : AddProperties(object, names, arraysize(names));
1067 5 : CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
1068 5 : CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
1069 5 : CHECK(!object->map()->is_dictionary_map());
1070 5 : objects.push_back(object);
1071 : }
1072 :
1073 : {
1074 : // Fast object, all inobject properties.
1075 : int inobject_properties = arraysize(names) * 2;
1076 5 : Handle<Map> map = Map::Create(isolate, inobject_properties);
1077 5 : Handle<JSObject> object = factory->NewJSObjectFromMap(map);
1078 5 : AddProperties(object, names, arraysize(names));
1079 5 : CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
1080 5 : CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
1081 5 : CHECK(!object->map()->is_dictionary_map());
1082 5 : objects.push_back(object);
1083 : }
1084 :
1085 : {
1086 : // Fast object, half inobject properties.
1087 : int inobject_properties = arraysize(names) / 2;
1088 5 : Handle<Map> map = Map::Create(isolate, inobject_properties);
1089 5 : Handle<JSObject> object = factory->NewJSObjectFromMap(map);
1090 5 : AddProperties(object, names, arraysize(names));
1091 5 : CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
1092 5 : CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
1093 5 : CHECK(!object->map()->is_dictionary_map());
1094 5 : objects.push_back(object);
1095 : }
1096 :
1097 : {
1098 : // Dictionary mode object.
1099 : Handle<JSFunction> function =
1100 5 : factory->NewFunctionForTest(factory->empty_string());
1101 5 : Handle<JSObject> object = factory->NewJSObject(function);
1102 5 : AddProperties(object, names, arraysize(names));
1103 5 : JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, "test");
1104 :
1105 5 : JSObject::AddProperty(isolate, object, deleted_property_name, object, NONE);
1106 10 : CHECK(JSObject::DeleteProperty(object, deleted_property_name,
1107 : LanguageMode::kSloppy)
1108 : .FromJust());
1109 :
1110 5 : CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
1111 5 : CHECK(object->map()->is_dictionary_map());
1112 5 : objects.push_back(object);
1113 : }
1114 :
1115 : {
1116 : // Global object.
1117 : Handle<JSFunction> function =
1118 5 : factory->NewFunctionForTest(factory->empty_string());
1119 5 : JSFunction::EnsureHasInitialMap(function);
1120 10 : function->initial_map()->set_instance_type(JS_GLOBAL_OBJECT_TYPE);
1121 10 : function->initial_map()->set_is_prototype_map(true);
1122 5 : function->initial_map()->set_is_dictionary_map(true);
1123 5 : function->initial_map()->set_may_have_interesting_symbols(true);
1124 5 : Handle<JSObject> object = factory->NewJSGlobalObject(function);
1125 5 : AddProperties(object, names, arraysize(names));
1126 :
1127 5 : JSObject::AddProperty(isolate, object, deleted_property_name, object, NONE);
1128 10 : CHECK(JSObject::DeleteProperty(object, deleted_property_name,
1129 : LanguageMode::kSloppy)
1130 : .FromJust());
1131 :
1132 5 : CHECK_EQ(JS_GLOBAL_OBJECT_TYPE, object->map()->instance_type());
1133 5 : CHECK(object->map()->is_dictionary_map());
1134 5 : objects.push_back(object);
1135 : }
1136 :
1137 : {
1138 35 : for (Handle<JSObject> object : objects) {
1139 250 : for (size_t name_index = 0; name_index < arraysize(names); name_index++) {
1140 225 : Handle<Name> name = names[name_index];
1141 450 : CHECK(JSReceiver::HasProperty(object, name).FromJust());
1142 225 : ft.CheckTrue(object, name, expect_found);
1143 : }
1144 : }
1145 : }
1146 :
1147 : {
1148 : Handle<Name> non_existing_names[] = {
1149 : factory->NewSymbol(),
1150 : factory->InternalizeUtf8String("ne_a"),
1151 : factory->InternalizeUtf8String("ne_bb"),
1152 : factory->NewPrivateSymbol(),
1153 : factory->InternalizeUtf8String("ne_ccc"),
1154 : factory->InternalizeUtf8String("ne_dddd"),
1155 : deleted_property_name,
1156 35 : };
1157 35 : for (Handle<JSObject> object : objects) {
1158 200 : for (size_t key_index = 0; key_index < arraysize(non_existing_names);
1159 : key_index++) {
1160 175 : Handle<Name> name = non_existing_names[key_index];
1161 350 : CHECK(!JSReceiver::HasProperty(object, name).FromJust());
1162 175 : ft.CheckTrue(object, name, expect_not_found);
1163 : }
1164 : }
1165 : }
1166 :
1167 : {
1168 : Handle<JSFunction> function =
1169 5 : factory->NewFunctionForTest(factory->empty_string());
1170 10 : Handle<JSProxy> object = factory->NewJSProxy(function, objects[0]);
1171 5 : CHECK_EQ(JS_PROXY_TYPE, object->map()->instance_type());
1172 5 : ft.CheckTrue(object, names[0], expect_bailout);
1173 : }
1174 :
1175 : {
1176 5 : Handle<JSObject> object = isolate->global_proxy();
1177 5 : CHECK_EQ(JS_GLOBAL_PROXY_TYPE, object->map()->instance_type());
1178 5 : ft.CheckTrue(object, names[0], expect_bailout);
1179 5 : }
1180 5 : }
1181 :
1182 28342 : TEST(TryGetOwnProperty) {
1183 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1184 : Factory* factory = isolate->factory();
1185 :
1186 : const int kNumParams = 2;
1187 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1188 5 : CodeStubAssembler m(asm_tester.state());
1189 :
1190 5 : Handle<Symbol> not_found_symbol = factory->NewSymbol();
1191 5 : Handle<Symbol> bailout_symbol = factory->NewSymbol();
1192 : {
1193 5 : Node* object = m.Parameter(0);
1194 5 : Node* unique_name = m.Parameter(1);
1195 5 : Node* context = m.Parameter(kNumParams + 2);
1196 :
1197 5 : Variable var_value(&m, MachineRepresentation::kTagged);
1198 5 : Label if_found(&m), if_not_found(&m), if_bailout(&m);
1199 :
1200 10 : Node* map = m.LoadMap(object);
1201 10 : Node* instance_type = m.LoadMapInstanceType(map);
1202 :
1203 : m.TryGetOwnProperty(context, object, object, map, instance_type,
1204 : unique_name, &if_found, &var_value, &if_not_found,
1205 5 : &if_bailout);
1206 :
1207 5 : m.BIND(&if_found);
1208 10 : m.Return(var_value.value());
1209 :
1210 5 : m.BIND(&if_not_found);
1211 5 : m.Return(m.HeapConstant(not_found_symbol));
1212 :
1213 5 : m.BIND(&if_bailout);
1214 10 : m.Return(m.HeapConstant(bailout_symbol));
1215 : }
1216 :
1217 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1218 :
1219 : Handle<Name> deleted_property_name =
1220 5 : factory->InternalizeUtf8String("deleted");
1221 :
1222 : Handle<Name> names[] = {
1223 : factory->InternalizeUtf8String("bb"),
1224 : factory->NewSymbol(),
1225 : factory->InternalizeUtf8String("a"),
1226 : factory->InternalizeUtf8String("ccc"),
1227 : factory->InternalizeUtf8String("esajefe"),
1228 : factory->NewPrivateSymbol(),
1229 : factory->InternalizeUtf8String("eeeee"),
1230 : factory->InternalizeUtf8String("p1"),
1231 : factory->InternalizeUtf8String("acshw23e"),
1232 : factory->InternalizeUtf8String(""),
1233 : factory->InternalizeUtf8String("dddd"),
1234 : factory->NewPrivateSymbol(),
1235 : factory->InternalizeUtf8String("name"),
1236 : factory->InternalizeUtf8String("p2"),
1237 : factory->InternalizeUtf8String("p3"),
1238 : factory->InternalizeUtf8String("p4"),
1239 : factory->NewPrivateSymbol(),
1240 85 : };
1241 : Handle<Object> values[] = {
1242 : factory->NewFunctionForTest(factory->empty_string()),
1243 : factory->NewSymbol(),
1244 : factory->InternalizeUtf8String("a"),
1245 : CreateAccessorPair(&ft, "() => 188;", "() => 199;"),
1246 : factory->NewFunctionForTest(factory->InternalizeUtf8String("bb")),
1247 : factory->InternalizeUtf8String("ccc"),
1248 : CreateAccessorPair(&ft, "() => 88;", nullptr),
1249 : handle(Smi::FromInt(1), isolate),
1250 : factory->InternalizeUtf8String(""),
1251 : CreateAccessorPair(&ft, nullptr, "() => 99;"),
1252 : factory->NewHeapNumber(4.2),
1253 : handle(Smi::FromInt(153), isolate),
1254 : factory->NewJSObject(
1255 : factory->NewFunctionForTest(factory->empty_string())),
1256 : factory->NewPrivateSymbol(),
1257 60 : };
1258 : STATIC_ASSERT(arraysize(values) < arraysize(names));
1259 :
1260 5 : base::RandomNumberGenerator rand_gen(FLAG_random_seed);
1261 :
1262 : std::vector<Handle<JSObject>> objects;
1263 :
1264 : {
1265 : // Fast object, no inobject properties.
1266 : int inobject_properties = 0;
1267 5 : Handle<Map> map = Map::Create(isolate, inobject_properties);
1268 5 : Handle<JSObject> object = factory->NewJSObjectFromMap(map);
1269 : AddProperties(object, names, arraysize(names), values, arraysize(values),
1270 5 : rand_gen.NextInt());
1271 5 : CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
1272 5 : CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
1273 5 : CHECK(!object->map()->is_dictionary_map());
1274 5 : objects.push_back(object);
1275 : }
1276 :
1277 : {
1278 : // Fast object, all inobject properties.
1279 : int inobject_properties = arraysize(names) * 2;
1280 5 : Handle<Map> map = Map::Create(isolate, inobject_properties);
1281 5 : Handle<JSObject> object = factory->NewJSObjectFromMap(map);
1282 : AddProperties(object, names, arraysize(names), values, arraysize(values),
1283 5 : rand_gen.NextInt());
1284 5 : CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
1285 5 : CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
1286 5 : CHECK(!object->map()->is_dictionary_map());
1287 5 : objects.push_back(object);
1288 : }
1289 :
1290 : {
1291 : // Fast object, half inobject properties.
1292 : int inobject_properties = arraysize(names) / 2;
1293 5 : Handle<Map> map = Map::Create(isolate, inobject_properties);
1294 5 : Handle<JSObject> object = factory->NewJSObjectFromMap(map);
1295 : AddProperties(object, names, arraysize(names), values, arraysize(values),
1296 5 : rand_gen.NextInt());
1297 5 : CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
1298 5 : CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
1299 5 : CHECK(!object->map()->is_dictionary_map());
1300 5 : objects.push_back(object);
1301 : }
1302 :
1303 : {
1304 : // Dictionary mode object.
1305 : Handle<JSFunction> function =
1306 5 : factory->NewFunctionForTest(factory->empty_string());
1307 5 : Handle<JSObject> object = factory->NewJSObject(function);
1308 : AddProperties(object, names, arraysize(names), values, arraysize(values),
1309 5 : rand_gen.NextInt());
1310 5 : JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, "test");
1311 :
1312 5 : JSObject::AddProperty(isolate, object, deleted_property_name, object, NONE);
1313 10 : CHECK(JSObject::DeleteProperty(object, deleted_property_name,
1314 : LanguageMode::kSloppy)
1315 : .FromJust());
1316 :
1317 5 : CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
1318 5 : CHECK(object->map()->is_dictionary_map());
1319 5 : objects.push_back(object);
1320 : }
1321 :
1322 : {
1323 : // Global object.
1324 5 : Handle<JSGlobalObject> object = isolate->global_object();
1325 : AddProperties(object, names, arraysize(names), values, arraysize(values),
1326 5 : rand_gen.NextInt());
1327 :
1328 5 : JSObject::AddProperty(isolate, object, deleted_property_name, object, NONE);
1329 10 : CHECK(JSObject::DeleteProperty(object, deleted_property_name,
1330 : LanguageMode::kSloppy)
1331 : .FromJust());
1332 :
1333 5 : CHECK_EQ(JS_GLOBAL_OBJECT_TYPE, object->map()->instance_type());
1334 5 : CHECK(object->map()->is_dictionary_map());
1335 5 : objects.push_back(object);
1336 : }
1337 :
1338 : // TODO(ishell): test proxy and interceptors when they are supported.
1339 :
1340 : {
1341 35 : for (Handle<JSObject> object : objects) {
1342 450 : for (size_t name_index = 0; name_index < arraysize(names); name_index++) {
1343 425 : Handle<Name> name = names[name_index];
1344 : Handle<Object> expected_value =
1345 850 : JSReceiver::GetProperty(isolate, object, name).ToHandleChecked();
1346 850 : Handle<Object> value = ft.Call(object, name).ToHandleChecked();
1347 425 : CHECK(expected_value->SameValue(*value));
1348 : }
1349 : }
1350 : }
1351 :
1352 : {
1353 : Handle<Name> non_existing_names[] = {
1354 : factory->NewSymbol(),
1355 : factory->InternalizeUtf8String("ne_a"),
1356 : factory->InternalizeUtf8String("ne_bb"),
1357 : factory->NewPrivateSymbol(),
1358 : factory->InternalizeUtf8String("ne_ccc"),
1359 : factory->InternalizeUtf8String("ne_dddd"),
1360 : deleted_property_name,
1361 35 : };
1362 35 : for (Handle<JSObject> object : objects) {
1363 200 : for (size_t key_index = 0; key_index < arraysize(non_existing_names);
1364 : key_index++) {
1365 175 : Handle<Name> name = non_existing_names[key_index];
1366 : Handle<Object> expected_value =
1367 350 : JSReceiver::GetProperty(isolate, object, name).ToHandleChecked();
1368 350 : CHECK(expected_value->IsUndefined(isolate));
1369 350 : Handle<Object> value = ft.Call(object, name).ToHandleChecked();
1370 525 : CHECK_EQ(*not_found_symbol, *value);
1371 : }
1372 : }
1373 : }
1374 :
1375 : {
1376 : Handle<JSFunction> function =
1377 5 : factory->NewFunctionForTest(factory->empty_string());
1378 10 : Handle<JSProxy> object = factory->NewJSProxy(function, objects[0]);
1379 5 : CHECK_EQ(JS_PROXY_TYPE, object->map()->instance_type());
1380 10 : Handle<Object> value = ft.Call(object, names[0]).ToHandleChecked();
1381 : // Proxies are not supported yet.
1382 15 : CHECK_EQ(*bailout_symbol, *value);
1383 : }
1384 :
1385 : {
1386 5 : Handle<JSObject> object = isolate->global_proxy();
1387 5 : CHECK_EQ(JS_GLOBAL_PROXY_TYPE, object->map()->instance_type());
1388 : // Global proxies are not supported yet.
1389 10 : Handle<Object> value = ft.Call(object, names[0]).ToHandleChecked();
1390 15 : CHECK_EQ(*bailout_symbol, *value);
1391 5 : }
1392 5 : }
1393 :
1394 : namespace {
1395 :
1396 : void AddElement(Handle<JSObject> object, uint32_t index, Handle<Object> value,
1397 : PropertyAttributes attributes = NONE) {
1398 30 : JSObject::AddDataElement(object, index, value, attributes);
1399 : }
1400 :
1401 : } // namespace
1402 :
1403 28342 : TEST(TryLookupElement) {
1404 10 : Isolate* isolate(CcTest::InitIsolateOnce());
1405 :
1406 : const int kNumParams = 3;
1407 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1408 5 : CodeStubAssembler m(asm_tester.state());
1409 :
1410 : enum Result { kFound, kAbsent, kNotFound, kBailout };
1411 : {
1412 5 : Node* object = m.Parameter(0);
1413 15 : Node* index = m.SmiUntag(m.Parameter(1));
1414 5 : Node* expected_result = m.Parameter(2);
1415 :
1416 5 : Label passed(&m), failed(&m);
1417 5 : Label if_found(&m), if_not_found(&m), if_bailout(&m), if_absent(&m);
1418 :
1419 10 : Node* map = m.LoadMap(object);
1420 10 : Node* instance_type = m.LoadMapInstanceType(map);
1421 :
1422 : m.TryLookupElement(object, map, instance_type, index, &if_found, &if_absent,
1423 5 : &if_not_found, &if_bailout);
1424 :
1425 5 : m.BIND(&if_found);
1426 10 : m.Branch(m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
1427 5 : &passed, &failed);
1428 :
1429 5 : m.BIND(&if_absent);
1430 10 : m.Branch(m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kAbsent))),
1431 5 : &passed, &failed);
1432 :
1433 5 : m.BIND(&if_not_found);
1434 : m.Branch(
1435 10 : m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
1436 5 : &passed, &failed);
1437 :
1438 5 : m.BIND(&if_bailout);
1439 : m.Branch(
1440 10 : m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kBailout))),
1441 5 : &passed, &failed);
1442 :
1443 5 : m.BIND(&passed);
1444 10 : m.Return(m.BooleanConstant(true));
1445 :
1446 5 : m.BIND(&failed);
1447 15 : m.Return(m.BooleanConstant(false));
1448 : }
1449 :
1450 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1451 :
1452 : Factory* factory = isolate->factory();
1453 : Handle<Object> smi0(Smi::kZero, isolate);
1454 : Handle<Object> smi1(Smi::FromInt(1), isolate);
1455 : Handle<Object> smi7(Smi::FromInt(7), isolate);
1456 : Handle<Object> smi13(Smi::FromInt(13), isolate);
1457 : Handle<Object> smi42(Smi::FromInt(42), isolate);
1458 :
1459 : Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
1460 : Handle<Object> expect_absent(Smi::FromInt(kAbsent), isolate);
1461 : Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
1462 : Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate);
1463 :
1464 : #define CHECK_FOUND(object, index) \
1465 : CHECK(JSReceiver::HasElement(object, index).FromJust()); \
1466 : ft.CheckTrue(object, smi##index, expect_found);
1467 :
1468 : #define CHECK_NOT_FOUND(object, index) \
1469 : CHECK(!JSReceiver::HasElement(object, index).FromJust()); \
1470 : ft.CheckTrue(object, smi##index, expect_not_found);
1471 :
1472 : #define CHECK_ABSENT(object, index) \
1473 : { \
1474 : bool success; \
1475 : Handle<Smi> smi(Smi::FromInt(index), isolate); \
1476 : LookupIterator it = \
1477 : LookupIterator::PropertyOrElement(isolate, object, smi, &success); \
1478 : CHECK(success); \
1479 : CHECK(!JSReceiver::HasProperty(&it).FromJust()); \
1480 : ft.CheckTrue(object, smi, expect_absent); \
1481 : }
1482 :
1483 : {
1484 5 : Handle<JSArray> object = factory->NewJSArray(0, PACKED_SMI_ELEMENTS);
1485 : AddElement(object, 0, smi0);
1486 : AddElement(object, 1, smi0);
1487 5 : CHECK_EQ(PACKED_SMI_ELEMENTS, object->map()->elements_kind());
1488 :
1489 15 : CHECK_FOUND(object, 0);
1490 15 : CHECK_FOUND(object, 1);
1491 15 : CHECK_NOT_FOUND(object, 7);
1492 15 : CHECK_NOT_FOUND(object, 13);
1493 15 : CHECK_NOT_FOUND(object, 42);
1494 : }
1495 :
1496 : {
1497 5 : Handle<JSArray> object = factory->NewJSArray(0, HOLEY_SMI_ELEMENTS);
1498 : AddElement(object, 0, smi0);
1499 : AddElement(object, 13, smi0);
1500 5 : CHECK_EQ(HOLEY_SMI_ELEMENTS, object->map()->elements_kind());
1501 :
1502 15 : CHECK_FOUND(object, 0);
1503 15 : CHECK_NOT_FOUND(object, 1);
1504 15 : CHECK_NOT_FOUND(object, 7);
1505 15 : CHECK_FOUND(object, 13);
1506 15 : CHECK_NOT_FOUND(object, 42);
1507 : }
1508 :
1509 : {
1510 5 : Handle<JSArray> object = factory->NewJSArray(0, PACKED_ELEMENTS);
1511 : AddElement(object, 0, smi0);
1512 : AddElement(object, 1, smi0);
1513 5 : CHECK_EQ(PACKED_ELEMENTS, object->map()->elements_kind());
1514 :
1515 15 : CHECK_FOUND(object, 0);
1516 15 : CHECK_FOUND(object, 1);
1517 15 : CHECK_NOT_FOUND(object, 7);
1518 15 : CHECK_NOT_FOUND(object, 13);
1519 15 : CHECK_NOT_FOUND(object, 42);
1520 : }
1521 :
1522 : {
1523 5 : Handle<JSArray> object = factory->NewJSArray(0, HOLEY_ELEMENTS);
1524 : AddElement(object, 0, smi0);
1525 : AddElement(object, 13, smi0);
1526 5 : CHECK_EQ(HOLEY_ELEMENTS, object->map()->elements_kind());
1527 :
1528 15 : CHECK_FOUND(object, 0);
1529 15 : CHECK_NOT_FOUND(object, 1);
1530 15 : CHECK_NOT_FOUND(object, 7);
1531 15 : CHECK_FOUND(object, 13);
1532 15 : CHECK_NOT_FOUND(object, 42);
1533 : }
1534 :
1535 : {
1536 5 : Handle<JSTypedArray> object = factory->NewJSTypedArray(INT32_ELEMENTS, 2);
1537 5 : Local<v8::ArrayBuffer> buffer = Utils::ToLocal(object->GetBuffer());
1538 :
1539 5 : CHECK_EQ(INT32_ELEMENTS, object->map()->elements_kind());
1540 :
1541 15 : CHECK_FOUND(object, 0);
1542 15 : CHECK_FOUND(object, 1);
1543 15 : CHECK_ABSENT(object, -10);
1544 15 : CHECK_ABSENT(object, 13);
1545 15 : CHECK_ABSENT(object, 42);
1546 :
1547 5 : v8::ArrayBuffer::Contents contents = buffer->Externalize();
1548 5 : buffer->Detach();
1549 : isolate->array_buffer_allocator()->Free(contents.Data(),
1550 5 : contents.ByteLength());
1551 :
1552 15 : CHECK_ABSENT(object, 0);
1553 15 : CHECK_ABSENT(object, 1);
1554 15 : CHECK_ABSENT(object, -10);
1555 15 : CHECK_ABSENT(object, 13);
1556 15 : CHECK_ABSENT(object, 42);
1557 : }
1558 :
1559 : {
1560 5 : Handle<JSFunction> constructor = isolate->string_function();
1561 5 : Handle<JSObject> object = factory->NewJSObject(constructor);
1562 5 : Handle<String> str = factory->InternalizeUtf8String("ab");
1563 10 : Handle<JSValue>::cast(object)->set_value(*str);
1564 : AddElement(object, 13, smi0);
1565 5 : CHECK_EQ(FAST_STRING_WRAPPER_ELEMENTS, object->map()->elements_kind());
1566 :
1567 15 : CHECK_FOUND(object, 0);
1568 15 : CHECK_FOUND(object, 1);
1569 15 : CHECK_NOT_FOUND(object, 7);
1570 15 : CHECK_FOUND(object, 13);
1571 15 : CHECK_NOT_FOUND(object, 42);
1572 : }
1573 :
1574 : {
1575 5 : Handle<JSFunction> constructor = isolate->string_function();
1576 5 : Handle<JSObject> object = factory->NewJSObject(constructor);
1577 5 : Handle<String> str = factory->InternalizeUtf8String("ab");
1578 10 : Handle<JSValue>::cast(object)->set_value(*str);
1579 : AddElement(object, 13, smi0);
1580 5 : JSObject::NormalizeElements(object);
1581 5 : CHECK_EQ(SLOW_STRING_WRAPPER_ELEMENTS, object->map()->elements_kind());
1582 :
1583 15 : CHECK_FOUND(object, 0);
1584 15 : CHECK_FOUND(object, 1);
1585 15 : CHECK_NOT_FOUND(object, 7);
1586 15 : CHECK_FOUND(object, 13);
1587 15 : CHECK_NOT_FOUND(object, 42);
1588 : }
1589 :
1590 : // TODO(ishell): uncomment once NO_ELEMENTS kind is supported.
1591 : // {
1592 : // Handle<Map> map = Map::Create(isolate, 0);
1593 : // map->set_elements_kind(NO_ELEMENTS);
1594 : // Handle<JSObject> object = factory->NewJSObjectFromMap(map);
1595 : // CHECK_EQ(NO_ELEMENTS, object->map()->elements_kind());
1596 : //
1597 : // CHECK_NOT_FOUND(object, 0);
1598 : // CHECK_NOT_FOUND(object, 1);
1599 : // CHECK_NOT_FOUND(object, 7);
1600 : // CHECK_NOT_FOUND(object, 13);
1601 : // CHECK_NOT_FOUND(object, 42);
1602 : // }
1603 :
1604 : #undef CHECK_FOUND
1605 : #undef CHECK_NOT_FOUND
1606 :
1607 : {
1608 5 : Handle<JSArray> handler = factory->NewJSArray(0);
1609 : Handle<JSFunction> function =
1610 5 : factory->NewFunctionForTest(factory->empty_string());
1611 5 : Handle<JSProxy> object = factory->NewJSProxy(function, handler);
1612 5 : CHECK_EQ(JS_PROXY_TYPE, object->map()->instance_type());
1613 5 : ft.CheckTrue(object, smi0, expect_bailout);
1614 : }
1615 :
1616 : {
1617 5 : Handle<JSObject> object = isolate->global_object();
1618 5 : CHECK_EQ(JS_GLOBAL_OBJECT_TYPE, object->map()->instance_type());
1619 5 : ft.CheckTrue(object, smi0, expect_bailout);
1620 : }
1621 :
1622 : {
1623 5 : Handle<JSObject> object = isolate->global_proxy();
1624 5 : CHECK_EQ(JS_GLOBAL_PROXY_TYPE, object->map()->instance_type());
1625 5 : ft.CheckTrue(object, smi0, expect_bailout);
1626 5 : }
1627 5 : }
1628 :
1629 28342 : TEST(AllocateJSObjectFromMap) {
1630 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1631 : Factory* factory = isolate->factory();
1632 :
1633 : const int kNumParams = 3;
1634 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1635 5 : CodeStubAssembler m(asm_tester.state());
1636 :
1637 : {
1638 5 : Node* map = m.Parameter(0);
1639 5 : Node* properties = m.Parameter(1);
1640 5 : Node* elements = m.Parameter(2);
1641 :
1642 5 : Node* result = m.AllocateJSObjectFromMap(map, properties, elements);
1643 :
1644 5 : m.Return(result);
1645 : }
1646 :
1647 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1648 :
1649 : Handle<Map> maps[] = {
1650 15 : handle(isolate->object_function()->initial_map(), isolate),
1651 15 : handle(isolate->array_function()->initial_map(), isolate),
1652 10 : };
1653 :
1654 : {
1655 : Handle<FixedArray> empty_fixed_array = factory->empty_fixed_array();
1656 : Handle<PropertyArray> empty_property_array =
1657 : factory->empty_property_array();
1658 15 : for (size_t i = 0; i < arraysize(maps); i++) {
1659 10 : Handle<Map> map = maps[i];
1660 : Handle<JSObject> result = Handle<JSObject>::cast(
1661 20 : ft.Call(map, empty_fixed_array, empty_fixed_array).ToHandleChecked());
1662 30 : CHECK_EQ(result->map(), *map);
1663 30 : CHECK_EQ(result->property_array(), *empty_property_array);
1664 30 : CHECK_EQ(result->elements(), *empty_fixed_array);
1665 10 : CHECK(result->HasFastProperties());
1666 : #ifdef VERIFY_HEAP
1667 : isolate->heap()->Verify();
1668 : #endif
1669 : }
1670 : }
1671 :
1672 : {
1673 : // TODO(cbruni): handle in-object properties
1674 : Handle<JSObject> object = Handle<JSObject>::cast(
1675 : v8::Utils::OpenHandle(*CompileRun("var object = {a:1,b:2, 1:1, 2:2}; "
1676 5 : "object")));
1677 : JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
1678 5 : "Normalize");
1679 : Handle<JSObject> result = Handle<JSObject>::cast(
1680 : ft.Call(handle(object->map(), isolate),
1681 10 : handle(object->property_dictionary(), isolate),
1682 15 : handle(object->elements(), isolate))
1683 10 : .ToHandleChecked());
1684 15 : CHECK_EQ(result->map(), object->map());
1685 15 : CHECK_EQ(result->property_dictionary(), object->property_dictionary());
1686 5 : CHECK(!result->HasFastProperties());
1687 : #ifdef VERIFY_HEAP
1688 : isolate->heap()->Verify();
1689 : #endif
1690 5 : }
1691 : #undef VERIFY
1692 5 : }
1693 :
1694 28342 : TEST(AllocateNameDictionary) {
1695 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1696 :
1697 : const int kNumParams = 1;
1698 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1699 5 : CodeStubAssembler m(asm_tester.state());
1700 :
1701 : {
1702 5 : Node* capacity = m.Parameter(0);
1703 10 : Node* result = m.AllocateNameDictionary(m.SmiUntag(capacity));
1704 5 : m.Return(result);
1705 : }
1706 :
1707 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1708 :
1709 : {
1710 205 : for (int i = 0; i < 256; i = i * 1.1 + 1) {
1711 : Handle<Object> result =
1712 400 : ft.Call(handle(Smi::FromInt(i), isolate)).ToHandleChecked();
1713 200 : Handle<NameDictionary> dict = NameDictionary::New(isolate, i);
1714 : // Both dictionaries should be memory equal.
1715 : int size =
1716 200 : FixedArrayBase::kHeaderSize + (dict->length() - 1) * kPointerSize;
1717 600 : CHECK_EQ(0, memcmp(reinterpret_cast<void*>(dict->ptr()),
1718 : reinterpret_cast<void*>(result->ptr()), size));
1719 : }
1720 5 : }
1721 5 : }
1722 :
1723 28342 : TEST(PopAndReturnConstant) {
1724 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1725 :
1726 : const int kNumParams = 4;
1727 : const int kNumProgrammaticParams = 2;
1728 5 : CodeAssemblerTester asm_tester(isolate, kNumParams - kNumProgrammaticParams);
1729 5 : CodeStubAssembler m(asm_tester.state());
1730 :
1731 : // Call a function that return |kNumProgramaticParams| parameters in addition
1732 : // to those specified by the static descriptor. |kNumProgramaticParams| is
1733 : // specified as a constant.
1734 : m.PopAndReturn(m.Int32Constant(kNumProgrammaticParams),
1735 15 : m.SmiConstant(Smi::FromInt(1234)));
1736 :
1737 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1738 : Handle<Object> result;
1739 505 : for (int test_count = 0; test_count < 100; ++test_count) {
1740 : result = ft.Call(isolate->factory()->undefined_value(),
1741 : Handle<Smi>(Smi::FromInt(1234), isolate),
1742 : isolate->factory()->undefined_value(),
1743 500 : isolate->factory()->undefined_value())
1744 1000 : .ToHandleChecked();
1745 1000 : CHECK_EQ(1234, Handle<Smi>::cast(result)->value());
1746 5 : }
1747 5 : }
1748 :
1749 28342 : TEST(PopAndReturnVariable) {
1750 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1751 :
1752 : const int kNumParams = 4;
1753 : const int kNumProgrammaticParams = 2;
1754 5 : CodeAssemblerTester asm_tester(isolate, kNumParams - kNumProgrammaticParams);
1755 5 : CodeStubAssembler m(asm_tester.state());
1756 :
1757 : // Call a function that return |kNumProgramaticParams| parameters in addition
1758 : // to those specified by the static descriptor. |kNumProgramaticParams| is
1759 : // passed in as a parameter to the function so that it can't be recongized as
1760 : // a constant.
1761 20 : m.PopAndReturn(m.SmiUntag(m.Parameter(1)), m.SmiConstant(Smi::FromInt(1234)));
1762 :
1763 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1764 : Handle<Object> result;
1765 505 : for (int test_count = 0; test_count < 100; ++test_count) {
1766 : result = ft.Call(isolate->factory()->undefined_value(),
1767 : Handle<Smi>(Smi::FromInt(1234), isolate),
1768 : isolate->factory()->undefined_value(),
1769 500 : Handle<Smi>(Smi::FromInt(kNumProgrammaticParams), isolate))
1770 1000 : .ToHandleChecked();
1771 1000 : CHECK_EQ(1234, Handle<Smi>::cast(result)->value());
1772 5 : }
1773 5 : }
1774 :
1775 28342 : TEST(OneToTwoByteStringCopy) {
1776 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1777 :
1778 : const int kNumParams = 2;
1779 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1780 5 : CodeStubAssembler m(asm_tester.state());
1781 :
1782 : m.CopyStringCharacters(m.Parameter(0), m.Parameter(1), m.IntPtrConstant(0),
1783 : m.IntPtrConstant(0), m.IntPtrConstant(5),
1784 5 : String::ONE_BYTE_ENCODING, String::TWO_BYTE_ENCODING);
1785 10 : m.Return(m.SmiConstant(Smi::FromInt(0)));
1786 :
1787 5 : Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
1788 5 : uc16 array[] = {1000, 1001, 1002, 1003, 1004};
1789 : Vector<const uc16> str(array);
1790 : Handle<String> string2 =
1791 10 : isolate->factory()->NewStringFromTwoByte(str).ToHandleChecked();
1792 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1793 5 : ft.Call(string1, string2);
1794 : DisallowHeapAllocation no_gc;
1795 20 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[0],
1796 : Handle<SeqTwoByteString>::cast(string2)->GetChars(no_gc)[0]);
1797 20 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[1],
1798 : Handle<SeqTwoByteString>::cast(string2)->GetChars(no_gc)[1]);
1799 20 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[2],
1800 : Handle<SeqTwoByteString>::cast(string2)->GetChars(no_gc)[2]);
1801 20 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[3],
1802 : Handle<SeqTwoByteString>::cast(string2)->GetChars(no_gc)[3]);
1803 20 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[4],
1804 5 : Handle<SeqTwoByteString>::cast(string2)->GetChars(no_gc)[4]);
1805 5 : }
1806 :
1807 28342 : TEST(OneToOneByteStringCopy) {
1808 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1809 :
1810 : const int kNumParams = 2;
1811 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1812 5 : CodeStubAssembler m(asm_tester.state());
1813 :
1814 : m.CopyStringCharacters(m.Parameter(0), m.Parameter(1), m.IntPtrConstant(0),
1815 : m.IntPtrConstant(0), m.IntPtrConstant(5),
1816 5 : String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING);
1817 10 : m.Return(m.SmiConstant(Smi::FromInt(0)));
1818 :
1819 5 : Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
1820 5 : uint8_t array[] = {100, 101, 102, 103, 104};
1821 : Vector<const uint8_t> str(array);
1822 : Handle<String> string2 =
1823 10 : isolate->factory()->NewStringFromOneByte(str).ToHandleChecked();
1824 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1825 5 : ft.Call(string1, string2);
1826 : DisallowHeapAllocation no_gc;
1827 15 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[0],
1828 : Handle<SeqOneByteString>::cast(string2)->GetChars(no_gc)[0]);
1829 15 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[1],
1830 : Handle<SeqOneByteString>::cast(string2)->GetChars(no_gc)[1]);
1831 15 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[2],
1832 : Handle<SeqOneByteString>::cast(string2)->GetChars(no_gc)[2]);
1833 15 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[3],
1834 : Handle<SeqOneByteString>::cast(string2)->GetChars(no_gc)[3]);
1835 15 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[4],
1836 5 : Handle<SeqOneByteString>::cast(string2)->GetChars(no_gc)[4]);
1837 5 : }
1838 :
1839 28342 : TEST(OneToOneByteStringCopyNonZeroStart) {
1840 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1841 :
1842 : const int kNumParams = 2;
1843 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1844 5 : CodeStubAssembler m(asm_tester.state());
1845 :
1846 : m.CopyStringCharacters(m.Parameter(0), m.Parameter(1), m.IntPtrConstant(0),
1847 : m.IntPtrConstant(3), m.IntPtrConstant(2),
1848 5 : String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING);
1849 10 : m.Return(m.SmiConstant(Smi::FromInt(0)));
1850 :
1851 5 : Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
1852 5 : uint8_t array[] = {100, 101, 102, 103, 104};
1853 : Vector<const uint8_t> str(array);
1854 : Handle<String> string2 =
1855 10 : isolate->factory()->NewStringFromOneByte(str).ToHandleChecked();
1856 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1857 5 : ft.Call(string1, string2);
1858 : DisallowHeapAllocation no_gc;
1859 15 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[0],
1860 : Handle<SeqOneByteString>::cast(string2)->GetChars(no_gc)[3]);
1861 15 : CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars(no_gc)[1],
1862 : Handle<SeqOneByteString>::cast(string2)->GetChars(no_gc)[4]);
1863 15 : CHECK_EQ(100, Handle<SeqOneByteString>::cast(string2)->GetChars(no_gc)[0]);
1864 15 : CHECK_EQ(101, Handle<SeqOneByteString>::cast(string2)->GetChars(no_gc)[1]);
1865 20 : CHECK_EQ(102, Handle<SeqOneByteString>::cast(string2)->GetChars(no_gc)[2]);
1866 5 : }
1867 :
1868 28342 : TEST(TwoToTwoByteStringCopy) {
1869 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1870 :
1871 : const int kNumParams = 2;
1872 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1873 5 : CodeStubAssembler m(asm_tester.state());
1874 :
1875 : m.CopyStringCharacters(m.Parameter(0), m.Parameter(1), m.IntPtrConstant(0),
1876 : m.IntPtrConstant(0), m.IntPtrConstant(5),
1877 5 : String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING);
1878 10 : m.Return(m.SmiConstant(Smi::FromInt(0)));
1879 :
1880 5 : uc16 array1[] = {2000, 2001, 2002, 2003, 2004};
1881 : Vector<const uc16> str1(array1);
1882 : Handle<String> string1 =
1883 10 : isolate->factory()->NewStringFromTwoByte(str1).ToHandleChecked();
1884 5 : uc16 array2[] = {1000, 1001, 1002, 1003, 1004};
1885 : Vector<const uc16> str2(array2);
1886 : Handle<String> string2 =
1887 10 : isolate->factory()->NewStringFromTwoByte(str2).ToHandleChecked();
1888 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1889 5 : ft.Call(string1, string2);
1890 : DisallowHeapAllocation no_gc;
1891 15 : CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars(no_gc)[0],
1892 : Handle<SeqTwoByteString>::cast(string2)->GetChars(no_gc)[0]);
1893 15 : CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars(no_gc)[1],
1894 : Handle<SeqTwoByteString>::cast(string2)->GetChars(no_gc)[1]);
1895 15 : CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars(no_gc)[2],
1896 : Handle<SeqTwoByteString>::cast(string2)->GetChars(no_gc)[2]);
1897 15 : CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars(no_gc)[3],
1898 : Handle<SeqTwoByteString>::cast(string2)->GetChars(no_gc)[3]);
1899 15 : CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars(no_gc)[4],
1900 5 : Handle<SeqTwoByteString>::cast(string2)->GetChars(no_gc)[4]);
1901 5 : }
1902 :
1903 28342 : TEST(Arguments) {
1904 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1905 :
1906 : const int kNumParams = 4;
1907 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1908 5 : CodeStubAssembler m(asm_tester.state());
1909 :
1910 10 : CodeStubArguments arguments(&m, m.IntPtrConstant(3));
1911 :
1912 : CSA_ASSERT(
1913 : &m, m.WordEqual(arguments.AtIndex(0), m.SmiConstant(Smi::FromInt(12))));
1914 : CSA_ASSERT(
1915 : &m, m.WordEqual(arguments.AtIndex(1), m.SmiConstant(Smi::FromInt(13))));
1916 : CSA_ASSERT(
1917 : &m, m.WordEqual(arguments.AtIndex(2), m.SmiConstant(Smi::FromInt(14))));
1918 :
1919 10 : arguments.PopAndReturn(arguments.GetReceiver());
1920 :
1921 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1922 : Handle<Object> result = ft.Call(isolate->factory()->undefined_value(),
1923 : Handle<Smi>(Smi::FromInt(12), isolate),
1924 : Handle<Smi>(Smi::FromInt(13), isolate),
1925 5 : Handle<Smi>(Smi::FromInt(14), isolate))
1926 10 : .ToHandleChecked();
1927 20 : CHECK_EQ(*isolate->factory()->undefined_value(), *result);
1928 5 : }
1929 :
1930 28342 : TEST(ArgumentsWithSmiConstantIndices) {
1931 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1932 :
1933 : const int kNumParams = 4;
1934 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1935 5 : CodeStubAssembler m(asm_tester.state());
1936 :
1937 : CodeStubArguments arguments(&m, m.SmiConstant(3), nullptr,
1938 10 : CodeStubAssembler::SMI_PARAMETERS);
1939 :
1940 : CSA_ASSERT(&m,
1941 : m.WordEqual(arguments.AtIndex(m.SmiConstant(0),
1942 : CodeStubAssembler::SMI_PARAMETERS),
1943 : m.SmiConstant(Smi::FromInt(12))));
1944 : CSA_ASSERT(&m,
1945 : m.WordEqual(arguments.AtIndex(m.SmiConstant(1),
1946 : CodeStubAssembler::SMI_PARAMETERS),
1947 : m.SmiConstant(Smi::FromInt(13))));
1948 : CSA_ASSERT(&m,
1949 : m.WordEqual(arguments.AtIndex(m.SmiConstant(2),
1950 : CodeStubAssembler::SMI_PARAMETERS),
1951 : m.SmiConstant(Smi::FromInt(14))));
1952 :
1953 10 : arguments.PopAndReturn(arguments.GetReceiver());
1954 :
1955 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
1956 : Handle<Object> result = ft.Call(isolate->factory()->undefined_value(),
1957 : Handle<Smi>(Smi::FromInt(12), isolate),
1958 : Handle<Smi>(Smi::FromInt(13), isolate),
1959 5 : Handle<Smi>(Smi::FromInt(14), isolate))
1960 10 : .ToHandleChecked();
1961 20 : CHECK_EQ(*isolate->factory()->undefined_value(), *result);
1962 5 : }
1963 :
1964 0 : TNode<Smi> NonConstantSmi(CodeStubAssembler* m, int value) {
1965 : // Generate a SMI with the given value and feed it through a Phi so it can't
1966 : // be inferred to be constant.
1967 0 : Variable var(m, MachineRepresentation::kTagged, m->SmiConstant(value));
1968 0 : Label dummy_done(m);
1969 : // Even though the Goto always executes, it will taint the variable and thus
1970 : // make it appear non-constant when used later.
1971 0 : m->GotoIf(m->Int32Constant(1), &dummy_done);
1972 0 : var.Bind(m->SmiConstant(value));
1973 0 : m->Goto(&dummy_done);
1974 0 : m->BIND(&dummy_done);
1975 :
1976 : // Ensure that the above hackery actually created a non-constant SMI.
1977 0 : Smi smi_constant;
1978 0 : CHECK(!m->ToSmiConstant(var.value(), &smi_constant));
1979 :
1980 0 : return m->UncheckedCast<Smi>(var.value());
1981 : }
1982 :
1983 28342 : TEST(ArgumentsWithSmiIndices) {
1984 5 : Isolate* isolate(CcTest::InitIsolateOnce());
1985 :
1986 : const int kNumParams = 4;
1987 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
1988 5 : CodeStubAssembler m(asm_tester.state());
1989 :
1990 : CodeStubArguments arguments(&m, m.SmiConstant(3), nullptr,
1991 10 : CodeStubAssembler::SMI_PARAMETERS);
1992 :
1993 : CSA_ASSERT(&m,
1994 : m.WordEqual(arguments.AtIndex(NonConstantSmi(&m, 0),
1995 : CodeStubAssembler::SMI_PARAMETERS),
1996 : m.SmiConstant(Smi::FromInt(12))));
1997 : CSA_ASSERT(&m,
1998 : m.WordEqual(arguments.AtIndex(NonConstantSmi(&m, 1),
1999 : CodeStubAssembler::SMI_PARAMETERS),
2000 : m.SmiConstant(Smi::FromInt(13))));
2001 : CSA_ASSERT(&m,
2002 : m.WordEqual(arguments.AtIndex(NonConstantSmi(&m, 2),
2003 : CodeStubAssembler::SMI_PARAMETERS),
2004 : m.SmiConstant(Smi::FromInt(14))));
2005 :
2006 10 : arguments.PopAndReturn(arguments.GetReceiver());
2007 :
2008 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2009 : Handle<Object> result = ft.Call(isolate->factory()->undefined_value(),
2010 : Handle<Smi>(Smi::FromInt(12), isolate),
2011 : Handle<Smi>(Smi::FromInt(13), isolate),
2012 5 : Handle<Smi>(Smi::FromInt(14), isolate))
2013 10 : .ToHandleChecked();
2014 20 : CHECK_EQ(*isolate->factory()->undefined_value(), *result);
2015 5 : }
2016 :
2017 28342 : TEST(ArgumentsForEach) {
2018 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2019 :
2020 : const int kNumParams = 4;
2021 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2022 5 : CodeStubAssembler m(asm_tester.state());
2023 :
2024 10 : CodeStubArguments arguments(&m, m.IntPtrConstant(3));
2025 :
2026 : TVariable<Smi> sum(&m);
2027 10 : CodeAssemblerVariableList list({&sum}, m.zone());
2028 :
2029 5 : sum = m.SmiConstant(0);
2030 :
2031 5 : arguments.ForEach(list, [&m, &sum](Node* arg) {
2032 10 : sum = m.SmiAdd(sum.value(), m.CAST(arg));
2033 15 : });
2034 :
2035 5 : arguments.PopAndReturn(sum.value());
2036 :
2037 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2038 : Handle<Object> result = ft.Call(isolate->factory()->undefined_value(),
2039 : Handle<Smi>(Smi::FromInt(12), isolate),
2040 : Handle<Smi>(Smi::FromInt(13), isolate),
2041 5 : Handle<Smi>(Smi::FromInt(14), isolate))
2042 10 : .ToHandleChecked();
2043 15 : CHECK_EQ(Smi::FromInt(12 + 13 + 14), *result);
2044 5 : }
2045 :
2046 28342 : TEST(IsDebugActive) {
2047 10 : Isolate* isolate(CcTest::InitIsolateOnce());
2048 :
2049 : const int kNumParams = 1;
2050 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2051 5 : CodeStubAssembler m(asm_tester.state());
2052 :
2053 5 : Label if_active(&m), if_not_active(&m);
2054 :
2055 10 : m.Branch(m.IsDebugActive(), &if_active, &if_not_active);
2056 5 : m.BIND(&if_active);
2057 10 : m.Return(m.TrueConstant());
2058 5 : m.BIND(&if_not_active);
2059 10 : m.Return(m.FalseConstant());
2060 :
2061 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2062 5 : CHECK(!isolate->debug()->is_active());
2063 : Handle<Object> result =
2064 10 : ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2065 15 : CHECK_EQ(ReadOnlyRoots(isolate).false_value(), *result);
2066 :
2067 : bool* debug_is_active = reinterpret_cast<bool*>(
2068 10 : ExternalReference::debug_is_active_address(isolate).address());
2069 :
2070 : // Cheat to enable debug (TODO: do this properly).
2071 5 : *debug_is_active = true;
2072 :
2073 10 : result = ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2074 15 : CHECK_EQ(ReadOnlyRoots(isolate).true_value(), *result);
2075 :
2076 : // Reset debug mode.
2077 10 : *debug_is_active = false;
2078 5 : }
2079 :
2080 : class AppendJSArrayCodeStubAssembler : public CodeStubAssembler {
2081 : public:
2082 : AppendJSArrayCodeStubAssembler(compiler::CodeAssemblerState* state,
2083 : ElementsKind kind)
2084 45 : : CodeStubAssembler(state), kind_(kind) {}
2085 :
2086 45 : void TestAppendJSArrayImpl(Isolate* isolate, CodeAssemblerTester* csa_tester,
2087 : Object o1, Object o2, Object o3, Object o4,
2088 : int initial_size, int result_size) {
2089 : Handle<JSArray> array = isolate->factory()->NewJSArray(
2090 45 : kind_, 2, initial_size, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
2091 : Object::SetElement(isolate, array, 0, Handle<Smi>(Smi::FromInt(1), isolate),
2092 45 : LanguageMode::kSloppy)
2093 90 : .Check();
2094 : Object::SetElement(isolate, array, 1, Handle<Smi>(Smi::FromInt(2), isolate),
2095 45 : LanguageMode::kSloppy)
2096 90 : .Check();
2097 135 : CodeStubArguments args(this, IntPtrConstant(kNumParams));
2098 : TVariable<IntPtrT> arg_index(this);
2099 45 : Label bailout(this);
2100 45 : arg_index = IntPtrConstant(0);
2101 : Node* length = BuildAppendJSArray(kind_, HeapConstant(array), &args,
2102 90 : &arg_index, &bailout);
2103 45 : Return(length);
2104 :
2105 45 : BIND(&bailout);
2106 135 : Return(SmiTag(IntPtrAdd(arg_index.value(), IntPtrConstant(2))));
2107 :
2108 45 : FunctionTester ft(csa_tester->GenerateCode(), kNumParams);
2109 :
2110 : Handle<Object> result =
2111 : ft.Call(Handle<Object>(o1, isolate), Handle<Object>(o2, isolate),
2112 45 : Handle<Object>(o3, isolate), Handle<Object>(o4, isolate))
2113 90 : .ToHandleChecked();
2114 :
2115 45 : CHECK_EQ(kind_, array->GetElementsKind());
2116 90 : CHECK_EQ(result_size, Handle<Smi>::cast(result)->value());
2117 45 : CHECK_EQ(result_size, Smi::ToInt(array->length()));
2118 90 : Object obj = *JSObject::GetElement(isolate, array, 2).ToHandleChecked();
2119 45 : HeapObject undefined_value = ReadOnlyRoots(isolate).undefined_value();
2120 90 : CHECK_EQ(result_size < 3 ? undefined_value : o1, obj);
2121 90 : obj = *JSObject::GetElement(isolate, array, 3).ToHandleChecked();
2122 90 : CHECK_EQ(result_size < 4 ? undefined_value : o2, obj);
2123 90 : obj = *JSObject::GetElement(isolate, array, 4).ToHandleChecked();
2124 90 : CHECK_EQ(result_size < 5 ? undefined_value : o3, obj);
2125 90 : obj = *JSObject::GetElement(isolate, array, 5).ToHandleChecked();
2126 90 : CHECK_EQ(result_size < 6 ? undefined_value : o4, obj);
2127 45 : }
2128 :
2129 45 : static void TestAppendJSArray(Isolate* isolate, ElementsKind kind, Object o1,
2130 : Object o2, Object o3, Object o4,
2131 : int initial_size, int result_size) {
2132 45 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2133 : AppendJSArrayCodeStubAssembler m(asm_tester.state(), kind);
2134 : m.TestAppendJSArrayImpl(isolate, &asm_tester, o1, o2, o3, o4, initial_size,
2135 90 : result_size);
2136 45 : }
2137 :
2138 : private:
2139 : static const int kNumParams = 4;
2140 : ElementsKind kind_;
2141 : };
2142 :
2143 28342 : TEST(BuildAppendJSArrayFastElement) {
2144 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2145 : AppendJSArrayCodeStubAssembler::TestAppendJSArray(
2146 : isolate, PACKED_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
2147 5 : Smi::FromInt(5), Smi::FromInt(6), 6, 6);
2148 5 : }
2149 :
2150 28342 : TEST(BuildAppendJSArrayFastElementGrow) {
2151 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2152 : AppendJSArrayCodeStubAssembler::TestAppendJSArray(
2153 : isolate, PACKED_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
2154 5 : Smi::FromInt(5), Smi::FromInt(6), 2, 6);
2155 5 : }
2156 :
2157 28342 : TEST(BuildAppendJSArrayFastSmiElement) {
2158 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2159 : AppendJSArrayCodeStubAssembler::TestAppendJSArray(
2160 : isolate, PACKED_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
2161 5 : Smi::FromInt(5), Smi::FromInt(6), 6, 6);
2162 5 : }
2163 :
2164 28342 : TEST(BuildAppendJSArrayFastSmiElementGrow) {
2165 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2166 : AppendJSArrayCodeStubAssembler::TestAppendJSArray(
2167 : isolate, PACKED_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
2168 5 : Smi::FromInt(5), Smi::FromInt(6), 2, 6);
2169 5 : }
2170 :
2171 28342 : TEST(BuildAppendJSArrayFastSmiElementObject) {
2172 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2173 : AppendJSArrayCodeStubAssembler::TestAppendJSArray(
2174 : isolate, PACKED_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
2175 10 : ReadOnlyRoots(isolate).undefined_value(), Smi::FromInt(6), 6, 4);
2176 5 : }
2177 :
2178 28342 : TEST(BuildAppendJSArrayFastSmiElementObjectGrow) {
2179 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2180 : AppendJSArrayCodeStubAssembler::TestAppendJSArray(
2181 : isolate, PACKED_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
2182 10 : ReadOnlyRoots(isolate).undefined_value(), Smi::FromInt(6), 2, 4);
2183 5 : }
2184 :
2185 28342 : TEST(BuildAppendJSArrayFastDoubleElements) {
2186 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2187 : AppendJSArrayCodeStubAssembler::TestAppendJSArray(
2188 : isolate, PACKED_DOUBLE_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
2189 5 : Smi::FromInt(5), Smi::FromInt(6), 6, 6);
2190 5 : }
2191 :
2192 28342 : TEST(BuildAppendJSArrayFastDoubleElementsGrow) {
2193 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2194 : AppendJSArrayCodeStubAssembler::TestAppendJSArray(
2195 : isolate, PACKED_DOUBLE_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
2196 5 : Smi::FromInt(5), Smi::FromInt(6), 2, 6);
2197 5 : }
2198 :
2199 28342 : TEST(BuildAppendJSArrayFastDoubleElementsObject) {
2200 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2201 : AppendJSArrayCodeStubAssembler::TestAppendJSArray(
2202 : isolate, PACKED_DOUBLE_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
2203 10 : ReadOnlyRoots(isolate).undefined_value(), Smi::FromInt(6), 6, 4);
2204 5 : }
2205 :
2206 : namespace {
2207 :
2208 : template <typename Stub, typename... Args>
2209 : void Recompile(Args... args) {
2210 : Stub stub(args...);
2211 : stub.DeleteStubFromCacheForTesting();
2212 : stub.GetCode();
2213 : }
2214 :
2215 : } // namespace
2216 :
2217 0 : void CustomPromiseHook(v8::PromiseHookType type, v8::Local<v8::Promise> promise,
2218 0 : v8::Local<v8::Value> parentPromise) {}
2219 :
2220 28342 : TEST(IsPromiseHookEnabled) {
2221 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2222 :
2223 : const int kNumParams = 1;
2224 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2225 5 : CodeStubAssembler m(asm_tester.state());
2226 :
2227 : m.Return(
2228 15 : m.SelectBooleanConstant(m.IsPromiseHookEnabledOrHasAsyncEventDelegate()));
2229 :
2230 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2231 : Handle<Object> result =
2232 10 : ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2233 15 : CHECK_EQ(ReadOnlyRoots(isolate).false_value(), *result);
2234 :
2235 5 : isolate->SetPromiseHook(CustomPromiseHook);
2236 10 : result = ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2237 15 : CHECK_EQ(ReadOnlyRoots(isolate).true_value(), *result);
2238 :
2239 5 : isolate->SetPromiseHook(nullptr);
2240 10 : result = ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2241 20 : CHECK_EQ(ReadOnlyRoots(isolate).false_value(), *result);
2242 5 : }
2243 :
2244 28342 : TEST(AllocateAndInitJSPromise) {
2245 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2246 :
2247 : const int kNumParams = 1;
2248 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2249 : PromiseBuiltinsAssembler m(asm_tester.state());
2250 :
2251 5 : Node* const context = m.Parameter(kNumParams + 2);
2252 5 : Node* const promise = m.AllocateAndInitJSPromise(context);
2253 5 : m.Return(promise);
2254 :
2255 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2256 : Handle<Object> result =
2257 10 : ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2258 15 : CHECK(result->IsJSPromise());
2259 5 : }
2260 :
2261 28342 : TEST(AllocateAndSetJSPromise) {
2262 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2263 :
2264 : const int kNumParams = 1;
2265 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2266 : PromiseBuiltinsAssembler m(asm_tester.state());
2267 :
2268 5 : Node* const context = m.Parameter(kNumParams + 2);
2269 : Node* const promise = m.AllocateAndSetJSPromise(
2270 10 : context, v8::Promise::kRejected, m.SmiConstant(1));
2271 5 : m.Return(promise);
2272 :
2273 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2274 : Handle<Object> result =
2275 10 : ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2276 10 : CHECK(result->IsJSPromise());
2277 5 : Handle<JSPromise> js_promise = Handle<JSPromise>::cast(result);
2278 5 : CHECK_EQ(v8::Promise::kRejected, js_promise->status());
2279 15 : CHECK_EQ(Smi::FromInt(1), js_promise->result());
2280 10 : CHECK(!js_promise->has_handler());
2281 5 : }
2282 :
2283 28342 : TEST(IsSymbol) {
2284 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2285 :
2286 : const int kNumParams = 1;
2287 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2288 5 : CodeStubAssembler m(asm_tester.state());
2289 :
2290 5 : Node* const symbol = m.Parameter(0);
2291 15 : m.Return(m.SelectBooleanConstant(m.IsSymbol(symbol)));
2292 :
2293 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2294 : Handle<Object> result =
2295 10 : ft.Call(isolate->factory()->NewSymbol()).ToHandleChecked();
2296 15 : CHECK_EQ(ReadOnlyRoots(isolate).true_value(), *result);
2297 :
2298 10 : result = ft.Call(isolate->factory()->empty_string()).ToHandleChecked();
2299 20 : CHECK_EQ(ReadOnlyRoots(isolate).false_value(), *result);
2300 5 : }
2301 :
2302 28342 : TEST(IsPrivateSymbol) {
2303 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2304 :
2305 : const int kNumParams = 1;
2306 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2307 5 : CodeStubAssembler m(asm_tester.state());
2308 :
2309 5 : Node* const symbol = m.Parameter(0);
2310 15 : m.Return(m.SelectBooleanConstant(m.IsPrivateSymbol(symbol)));
2311 :
2312 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2313 : Handle<Object> result =
2314 10 : ft.Call(isolate->factory()->NewSymbol()).ToHandleChecked();
2315 15 : CHECK_EQ(ReadOnlyRoots(isolate).false_value(), *result);
2316 :
2317 10 : result = ft.Call(isolate->factory()->empty_string()).ToHandleChecked();
2318 15 : CHECK_EQ(ReadOnlyRoots(isolate).false_value(), *result);
2319 :
2320 10 : result = ft.Call(isolate->factory()->NewPrivateSymbol()).ToHandleChecked();
2321 20 : CHECK_EQ(ReadOnlyRoots(isolate).true_value(), *result);
2322 5 : }
2323 :
2324 28342 : TEST(PromiseHasHandler) {
2325 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2326 :
2327 : const int kNumParams = 1;
2328 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2329 : PromiseBuiltinsAssembler m(asm_tester.state());
2330 :
2331 5 : Node* const context = m.Parameter(kNumParams + 2);
2332 : Node* const promise =
2333 10 : m.AllocateAndInitJSPromise(context, m.UndefinedConstant());
2334 15 : m.Return(m.SelectBooleanConstant(m.PromiseHasHandler(promise)));
2335 :
2336 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2337 : Handle<Object> result =
2338 10 : ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2339 20 : CHECK_EQ(ReadOnlyRoots(isolate).false_value(), *result);
2340 5 : }
2341 :
2342 28342 : TEST(CreatePromiseResolvingFunctionsContext) {
2343 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2344 :
2345 : const int kNumParams = 1;
2346 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2347 : PromiseBuiltinsAssembler m(asm_tester.state());
2348 :
2349 5 : Node* const context = m.Parameter(kNumParams + 2);
2350 10 : Node* const native_context = m.LoadNativeContext(context);
2351 : Node* const promise =
2352 10 : m.AllocateAndInitJSPromise(context, m.UndefinedConstant());
2353 : Node* const promise_context = m.CreatePromiseResolvingFunctionsContext(
2354 10 : promise, m.BooleanConstant(false), native_context);
2355 5 : m.Return(promise_context);
2356 :
2357 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2358 : Handle<Object> result =
2359 10 : ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2360 10 : CHECK(result->IsContext());
2361 5 : Handle<Context> context_js = Handle<Context>::cast(result);
2362 15 : CHECK_EQ(isolate->native_context()->scope_info(), context_js->scope_info());
2363 15 : CHECK_EQ(ReadOnlyRoots(isolate).the_hole_value(), context_js->extension());
2364 15 : CHECK_EQ(*isolate->native_context(), context_js->native_context());
2365 15 : CHECK(context_js->get(PromiseBuiltins::kPromiseSlot)->IsJSPromise());
2366 20 : CHECK_EQ(ReadOnlyRoots(isolate).false_value(),
2367 5 : context_js->get(PromiseBuiltins::kDebugEventSlot));
2368 5 : }
2369 :
2370 28342 : TEST(CreatePromiseResolvingFunctions) {
2371 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2372 :
2373 : const int kNumParams = 1;
2374 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2375 : PromiseBuiltinsAssembler m(asm_tester.state());
2376 :
2377 5 : Node* const context = m.Parameter(kNumParams + 2);
2378 10 : Node* const native_context = m.LoadNativeContext(context);
2379 : Node* const promise =
2380 10 : m.AllocateAndInitJSPromise(context, m.UndefinedConstant());
2381 : Node *resolve, *reject;
2382 10 : std::tie(resolve, reject) = m.CreatePromiseResolvingFunctions(
2383 10 : promise, m.BooleanConstant(false), native_context);
2384 10 : Node* const kSize = m.IntPtrConstant(2);
2385 : TNode<FixedArray> const arr =
2386 5 : m.Cast(m.AllocateFixedArray(PACKED_ELEMENTS, kSize));
2387 5 : m.StoreFixedArrayElement(arr, 0, resolve);
2388 5 : m.StoreFixedArrayElement(arr, 1, reject);
2389 5 : m.Return(arr);
2390 :
2391 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2392 : Handle<Object> result_obj =
2393 10 : ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2394 10 : CHECK(result_obj->IsFixedArray());
2395 5 : Handle<FixedArray> result_arr = Handle<FixedArray>::cast(result_obj);
2396 10 : CHECK(result_arr->get(0)->IsJSFunction());
2397 15 : CHECK(result_arr->get(1)->IsJSFunction());
2398 5 : }
2399 :
2400 28342 : TEST(NewElementsCapacity) {
2401 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2402 5 : CodeAssemblerTester asm_tester(isolate, 1);
2403 5 : CodeStubAssembler m(asm_tester.state());
2404 : m.Return(m.SmiTag(m.CalculateNewElementsCapacity(
2405 25 : m.SmiUntag(m.Parameter(0)), CodeStubAssembler::INTPTR_PARAMETERS)));
2406 :
2407 5 : FunctionTester ft(asm_tester.GenerateCode(), 1);
2408 : Handle<Smi> test_value = Handle<Smi>(Smi::FromInt(0), isolate);
2409 5 : Handle<Smi> result_obj = ft.CallChecked<Smi>(test_value);
2410 15 : CHECK_EQ(
2411 : result_obj->value(),
2412 : static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
2413 : test_value = Handle<Smi>(Smi::FromInt(1), isolate);
2414 5 : result_obj = ft.CallChecked<Smi>(test_value);
2415 15 : CHECK_EQ(
2416 : result_obj->value(),
2417 : static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
2418 : test_value = Handle<Smi>(Smi::FromInt(2), isolate);
2419 5 : result_obj = ft.CallChecked<Smi>(test_value);
2420 15 : CHECK_EQ(
2421 : result_obj->value(),
2422 : static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
2423 : test_value = Handle<Smi>(Smi::FromInt(1025), isolate);
2424 5 : result_obj = ft.CallChecked<Smi>(test_value);
2425 15 : CHECK_EQ(
2426 : result_obj->value(),
2427 5 : static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
2428 5 : }
2429 :
2430 28342 : TEST(NewElementsCapacitySmi) {
2431 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2432 5 : CodeAssemblerTester asm_tester(isolate, 1);
2433 5 : CodeStubAssembler m(asm_tester.state());
2434 : m.Return(m.CalculateNewElementsCapacity(m.Parameter(0),
2435 10 : CodeStubAssembler::SMI_PARAMETERS));
2436 :
2437 5 : FunctionTester ft(asm_tester.GenerateCode(), 1);
2438 : Handle<Smi> test_value = Handle<Smi>(Smi::FromInt(0), isolate);
2439 5 : Handle<Smi> result_obj = ft.CallChecked<Smi>(test_value);
2440 15 : CHECK_EQ(
2441 : result_obj->value(),
2442 : static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
2443 : test_value = Handle<Smi>(Smi::FromInt(1), isolate);
2444 5 : result_obj = ft.CallChecked<Smi>(test_value);
2445 15 : CHECK_EQ(
2446 : result_obj->value(),
2447 : static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
2448 : test_value = Handle<Smi>(Smi::FromInt(2), isolate);
2449 5 : result_obj = ft.CallChecked<Smi>(test_value);
2450 15 : CHECK_EQ(
2451 : result_obj->value(),
2452 : static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
2453 : test_value = Handle<Smi>(Smi::FromInt(1025), isolate);
2454 5 : result_obj = ft.CallChecked<Smi>(test_value);
2455 15 : CHECK_EQ(
2456 : result_obj->value(),
2457 5 : static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
2458 5 : }
2459 :
2460 28342 : TEST(AllocateFunctionWithMapAndContext) {
2461 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2462 :
2463 : const int kNumParams = 1;
2464 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2465 : PromiseBuiltinsAssembler m(asm_tester.state());
2466 :
2467 5 : Node* const context = m.Parameter(kNumParams + 2);
2468 10 : Node* const native_context = m.LoadNativeContext(context);
2469 : Node* const promise =
2470 10 : m.AllocateAndInitJSPromise(context, m.UndefinedConstant());
2471 : Node* promise_context = m.CreatePromiseResolvingFunctionsContext(
2472 10 : promise, m.BooleanConstant(false), native_context);
2473 : Node* resolve_info = m.LoadContextElement(
2474 : native_context,
2475 10 : Context::PROMISE_CAPABILITY_DEFAULT_RESOLVE_SHARED_FUN_INDEX);
2476 : Node* const map = m.LoadContextElement(
2477 10 : native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
2478 : Node* const resolve =
2479 5 : m.AllocateFunctionWithMapAndContext(map, resolve_info, promise_context);
2480 5 : m.Return(resolve);
2481 :
2482 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2483 : Handle<Object> result_obj =
2484 10 : ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2485 10 : CHECK(result_obj->IsJSFunction());
2486 5 : Handle<JSFunction> fun = Handle<JSFunction>::cast(result_obj);
2487 15 : CHECK_EQ(ReadOnlyRoots(isolate).empty_property_array(),
2488 : fun->property_array());
2489 15 : CHECK_EQ(ReadOnlyRoots(isolate).empty_fixed_array(), fun->elements());
2490 10 : CHECK_EQ(isolate->heap()->many_closures_cell(), fun->raw_feedback_cell());
2491 5 : CHECK(!fun->has_prototype_slot());
2492 15 : CHECK_EQ(*isolate->promise_capability_default_resolve_shared_fun(),
2493 : fun->shared());
2494 15 : CHECK_EQ(isolate->promise_capability_default_resolve_shared_fun()->GetCode(),
2495 5 : fun->code());
2496 5 : }
2497 :
2498 28342 : TEST(CreatePromiseGetCapabilitiesExecutorContext) {
2499 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2500 :
2501 : const int kNumParams = 1;
2502 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2503 : PromiseBuiltinsAssembler m(asm_tester.state());
2504 :
2505 5 : Node* const context = m.Parameter(kNumParams + 2);
2506 10 : Node* const native_context = m.LoadNativeContext(context);
2507 :
2508 10 : Node* const map = m.LoadRoot(RootIndex::kPromiseCapabilityMap);
2509 5 : Node* const capability = m.AllocateStruct(map);
2510 : m.StoreObjectFieldNoWriteBarrier(
2511 10 : capability, PromiseCapability::kPromiseOffset, m.UndefinedConstant());
2512 : m.StoreObjectFieldNoWriteBarrier(
2513 10 : capability, PromiseCapability::kResolveOffset, m.UndefinedConstant());
2514 : m.StoreObjectFieldNoWriteBarrier(capability, PromiseCapability::kRejectOffset,
2515 10 : m.UndefinedConstant());
2516 : Node* const executor_context =
2517 5 : m.CreatePromiseGetCapabilitiesExecutorContext(capability, native_context);
2518 5 : m.Return(executor_context);
2519 :
2520 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2521 : Handle<Object> result_obj =
2522 10 : ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2523 10 : CHECK(result_obj->IsContext());
2524 5 : Handle<Context> context_js = Handle<Context>::cast(result_obj);
2525 10 : CHECK_EQ(PromiseBuiltins::kCapabilitiesContextLength, context_js->length());
2526 15 : CHECK_EQ(isolate->native_context()->scope_info(), context_js->scope_info());
2527 15 : CHECK_EQ(ReadOnlyRoots(isolate).the_hole_value(), context_js->extension());
2528 15 : CHECK_EQ(*isolate->native_context(), context_js->native_context());
2529 15 : CHECK(
2530 5 : context_js->get(PromiseBuiltins::kCapabilitySlot)->IsPromiseCapability());
2531 5 : }
2532 :
2533 28342 : TEST(NewPromiseCapability) {
2534 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2535 :
2536 : { // Builtin Promise
2537 : const int kNumParams = 1;
2538 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2539 : PromiseBuiltinsAssembler m(asm_tester.state());
2540 :
2541 5 : Node* const context = m.Parameter(kNumParams + 2);
2542 10 : Node* const native_context = m.LoadNativeContext(context);
2543 : Node* const promise_constructor =
2544 10 : m.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
2545 :
2546 10 : Node* const debug_event = m.TrueConstant();
2547 : Node* const capability =
2548 : m.CallBuiltin(Builtins::kNewPromiseCapability, context,
2549 10 : promise_constructor, debug_event);
2550 5 : m.Return(capability);
2551 :
2552 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2553 :
2554 : Handle<Object> result_obj =
2555 10 : ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
2556 10 : CHECK(result_obj->IsPromiseCapability());
2557 : Handle<PromiseCapability> result =
2558 5 : Handle<PromiseCapability>::cast(result_obj);
2559 :
2560 10 : CHECK(result->promise()->IsJSPromise());
2561 10 : CHECK(result->resolve()->IsJSFunction());
2562 10 : CHECK(result->reject()->IsJSFunction());
2563 20 : CHECK_EQ(*isolate->promise_capability_default_reject_shared_fun(),
2564 : JSFunction::cast(result->reject())->shared());
2565 20 : CHECK_EQ(*isolate->promise_capability_default_resolve_shared_fun(),
2566 : JSFunction::cast(result->resolve())->shared());
2567 :
2568 : Handle<JSFunction> callbacks[] = {
2569 10 : handle(JSFunction::cast(result->resolve()), isolate),
2570 15 : handle(JSFunction::cast(result->reject()), isolate)};
2571 :
2572 15 : for (auto&& callback : callbacks) {
2573 20 : Handle<Context> context(Context::cast(callback->context()), isolate);
2574 30 : CHECK_EQ(isolate->native_context()->scope_info(), context->scope_info());
2575 30 : CHECK_EQ(ReadOnlyRoots(isolate).the_hole_value(), context->extension());
2576 30 : CHECK_EQ(*isolate->native_context(), context->native_context());
2577 20 : CHECK_EQ(PromiseBuiltins::kPromiseContextLength, context->length());
2578 40 : CHECK_EQ(context->get(PromiseBuiltins::kPromiseSlot), result->promise());
2579 5 : }
2580 : }
2581 :
2582 : { // Custom Promise
2583 : const int kNumParams = 2;
2584 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2585 : PromiseBuiltinsAssembler m(asm_tester.state());
2586 :
2587 5 : Node* const context = m.Parameter(kNumParams + 2);
2588 :
2589 5 : Node* const constructor = m.Parameter(1);
2590 10 : Node* const debug_event = m.TrueConstant();
2591 : Node* const capability = m.CallBuiltin(Builtins::kNewPromiseCapability,
2592 10 : context, constructor, debug_event);
2593 5 : m.Return(capability);
2594 :
2595 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2596 :
2597 : Handle<JSFunction> constructor_fn =
2598 : Handle<JSFunction>::cast(v8::Utils::OpenHandle(*CompileRun(
2599 : "(function FakePromise(executor) {"
2600 : " var self = this;"
2601 : " function resolve(value) { self.resolvedValue = value; }"
2602 : " function reject(reason) { self.rejectedReason = reason; }"
2603 : " executor(resolve, reject);"
2604 5 : "})")));
2605 :
2606 : Handle<Object> result_obj =
2607 : ft.Call(isolate->factory()->undefined_value(), constructor_fn)
2608 10 : .ToHandleChecked();
2609 10 : CHECK(result_obj->IsPromiseCapability());
2610 : Handle<PromiseCapability> result =
2611 5 : Handle<PromiseCapability>::cast(result_obj);
2612 :
2613 10 : CHECK(result->promise()->IsJSObject());
2614 10 : Handle<JSObject> promise(JSObject::cast(result->promise()), isolate);
2615 15 : CHECK_EQ(constructor_fn->prototype_or_initial_map(), promise->map());
2616 10 : CHECK(result->resolve()->IsJSFunction());
2617 10 : CHECK(result->reject()->IsJSFunction());
2618 :
2619 : Handle<String> resolved_str =
2620 5 : isolate->factory()->NewStringFromAsciiChecked("resolvedStr");
2621 : Handle<String> rejected_str =
2622 5 : isolate->factory()->NewStringFromAsciiChecked("rejectedStr");
2623 :
2624 : Handle<Object> argv1[] = {resolved_str};
2625 : Handle<Object> ret =
2626 : Execution::Call(isolate, handle(result->resolve(), isolate),
2627 10 : isolate->factory()->undefined_value(), 1, argv1)
2628 10 : .ToHandleChecked();
2629 :
2630 : Handle<Object> prop1 =
2631 5 : JSReceiver::GetProperty(isolate, promise, "resolvedValue")
2632 10 : .ToHandleChecked();
2633 15 : CHECK_EQ(*resolved_str, *prop1);
2634 :
2635 : Handle<Object> argv2[] = {rejected_str};
2636 : ret = Execution::Call(isolate, handle(result->reject(), isolate),
2637 10 : isolate->factory()->undefined_value(), 1, argv2)
2638 10 : .ToHandleChecked();
2639 : Handle<Object> prop2 =
2640 5 : JSReceiver::GetProperty(isolate, promise, "rejectedReason")
2641 10 : .ToHandleChecked();
2642 20 : CHECK_EQ(*rejected_str, *prop2);
2643 : }
2644 5 : }
2645 :
2646 28342 : TEST(DirectMemoryTest8BitWord32Immediate) {
2647 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2648 :
2649 : const int kNumParams = 0;
2650 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2651 5 : CodeStubAssembler m(asm_tester.state());
2652 5 : int8_t buffer[] = {1, 2, 4, 8, 17, 33, 65, 127};
2653 : const int element_count = 8;
2654 5 : Label bad(&m);
2655 :
2656 10 : Node* buffer_node = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer));
2657 45 : for (size_t i = 0; i < element_count; ++i) {
2658 320 : for (size_t j = 0; j < element_count; ++j) {
2659 : Node* loaded = m.LoadBufferObject(buffer_node, static_cast<int>(i),
2660 320 : MachineType::Uint8());
2661 960 : Node* masked = m.Word32And(loaded, m.Int32Constant(buffer[j]));
2662 320 : if ((buffer[j] & buffer[i]) != 0) {
2663 510 : m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
2664 : } else {
2665 450 : m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
2666 : }
2667 : }
2668 : }
2669 :
2670 10 : m.Return(m.SmiConstant(1));
2671 :
2672 5 : m.BIND(&bad);
2673 10 : m.Return(m.SmiConstant(0));
2674 :
2675 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2676 15 : CHECK_EQ(1, ft.CallChecked<Smi>()->value());
2677 5 : }
2678 :
2679 28342 : TEST(DirectMemoryTest16BitWord32Immediate) {
2680 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2681 : const int kNumParams = 0;
2682 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2683 5 : CodeStubAssembler m(asm_tester.state());
2684 5 : int16_t buffer[] = {156, 2234, 4544, 8444, 1723, 3888, 658, 1278};
2685 : const int element_count = 8;
2686 5 : Label bad(&m);
2687 :
2688 10 : Node* buffer_node = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer));
2689 45 : for (size_t i = 0; i < element_count; ++i) {
2690 320 : for (size_t j = 0; j < element_count; ++j) {
2691 : Node* loaded =
2692 : m.LoadBufferObject(buffer_node, static_cast<int>(i * sizeof(int16_t)),
2693 320 : MachineType::Uint16());
2694 960 : Node* masked = m.Word32And(loaded, m.Int32Constant(buffer[j]));
2695 320 : if ((buffer[j] & buffer[i]) != 0) {
2696 960 : m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
2697 : } else {
2698 0 : m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
2699 : }
2700 : }
2701 : }
2702 :
2703 10 : m.Return(m.SmiConstant(1));
2704 :
2705 5 : m.BIND(&bad);
2706 10 : m.Return(m.SmiConstant(0));
2707 :
2708 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2709 15 : CHECK_EQ(1, ft.CallChecked<Smi>()->value());
2710 5 : }
2711 :
2712 28342 : TEST(DirectMemoryTest8BitWord32) {
2713 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2714 : const int kNumParams = 0;
2715 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2716 5 : CodeStubAssembler m(asm_tester.state());
2717 5 : int8_t buffer[] = {1, 2, 4, 8, 17, 33, 65, 127, 67, 38};
2718 : const int element_count = 10;
2719 5 : Label bad(&m);
2720 : Node* constants[element_count];
2721 :
2722 10 : Node* buffer_node = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer));
2723 55 : for (size_t i = 0; i < element_count; ++i) {
2724 : constants[i] = m.LoadBufferObject(buffer_node, static_cast<int>(i),
2725 50 : MachineType::Uint8());
2726 : }
2727 :
2728 50 : for (size_t i = 0; i < element_count; ++i) {
2729 500 : for (size_t j = 0; j < element_count; ++j) {
2730 : Node* loaded = m.LoadBufferObject(buffer_node, static_cast<int>(i),
2731 500 : MachineType::Uint8());
2732 1500 : Node* masked = m.Word32And(loaded, constants[j]);
2733 500 : if ((buffer[j] & buffer[i]) != 0) {
2734 870 : m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
2735 : } else {
2736 630 : m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
2737 : }
2738 :
2739 2000 : masked = m.Word32And(constants[i], constants[j]);
2740 500 : if ((buffer[j] & buffer[i]) != 0) {
2741 870 : m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
2742 : } else {
2743 630 : m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
2744 : }
2745 : }
2746 : }
2747 :
2748 10 : m.Return(m.SmiConstant(1));
2749 :
2750 5 : m.BIND(&bad);
2751 10 : m.Return(m.SmiConstant(0));
2752 :
2753 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2754 15 : CHECK_EQ(1, ft.CallChecked<Smi>()->value());
2755 5 : }
2756 :
2757 28342 : TEST(DirectMemoryTest16BitWord32) {
2758 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2759 : const int kNumParams = 0;
2760 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2761 5 : CodeStubAssembler m(asm_tester.state());
2762 5 : int16_t buffer[] = {1, 2, 4, 8, 12345, 33, 65, 255, 67, 3823};
2763 : const int element_count = 10;
2764 5 : Label bad(&m);
2765 : Node* constants[element_count];
2766 :
2767 10 : Node* buffer_node1 = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer));
2768 55 : for (size_t i = 0; i < element_count; ++i) {
2769 : constants[i] =
2770 : m.LoadBufferObject(buffer_node1, static_cast<int>(i * sizeof(int16_t)),
2771 50 : MachineType::Uint16());
2772 : }
2773 10 : Node* buffer_node2 = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer));
2774 :
2775 55 : for (size_t i = 0; i < element_count; ++i) {
2776 500 : for (size_t j = 0; j < element_count; ++j) {
2777 : Node* loaded = m.LoadBufferObject(buffer_node1,
2778 : static_cast<int>(i * sizeof(int16_t)),
2779 500 : MachineType::Uint16());
2780 1500 : Node* masked = m.Word32And(loaded, constants[j]);
2781 500 : if ((buffer[j] & buffer[i]) != 0) {
2782 1020 : m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
2783 : } else {
2784 480 : m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
2785 : }
2786 :
2787 : // Force a memory access relative to a high-number register.
2788 : loaded = m.LoadBufferObject(buffer_node2,
2789 : static_cast<int>(i * sizeof(int16_t)),
2790 500 : MachineType::Uint16());
2791 1500 : masked = m.Word32And(loaded, constants[j]);
2792 500 : if ((buffer[j] & buffer[i]) != 0) {
2793 1020 : m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
2794 : } else {
2795 480 : m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
2796 : }
2797 :
2798 2000 : masked = m.Word32And(constants[i], constants[j]);
2799 500 : if ((buffer[j] & buffer[i]) != 0) {
2800 1020 : m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
2801 : } else {
2802 480 : m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
2803 : }
2804 : }
2805 : }
2806 :
2807 10 : m.Return(m.SmiConstant(1));
2808 :
2809 5 : m.BIND(&bad);
2810 10 : m.Return(m.SmiConstant(0));
2811 :
2812 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2813 15 : CHECK_EQ(1, ft.CallChecked<Smi>()->value());
2814 5 : }
2815 :
2816 28342 : TEST(LoadJSArrayElementsMap) {
2817 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2818 : const int kNumParams = 1;
2819 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2820 : {
2821 5 : CodeStubAssembler m(asm_tester.state());
2822 5 : Node* context = m.Parameter(kNumParams + 2);
2823 10 : Node* native_context = m.LoadNativeContext(context);
2824 15 : Node* kind = m.SmiToInt32(m.Parameter(0));
2825 10 : m.Return(m.LoadJSArrayElementsMap(kind, native_context));
2826 : }
2827 :
2828 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2829 35 : for (int kind = 0; kind <= HOLEY_DOUBLE_ELEMENTS; kind++) {
2830 : Handle<Map> csa_result =
2831 30 : ft.CallChecked<Map>(handle(Smi::FromInt(kind), isolate));
2832 : ElementsKind elements_kind = static_cast<ElementsKind>(kind);
2833 : Handle<Map> result(
2834 90 : isolate->native_context()->GetInitialJSArrayMap(elements_kind),
2835 60 : isolate);
2836 90 : CHECK_EQ(*csa_result, *result);
2837 5 : }
2838 5 : }
2839 :
2840 28342 : TEST(AllocateStruct) {
2841 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2842 :
2843 : const int kNumParams = 3;
2844 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2845 5 : CodeStubAssembler m(asm_tester.state());
2846 :
2847 : {
2848 5 : Node* map = m.Parameter(0);
2849 5 : Node* result = m.AllocateStruct(map);
2850 :
2851 5 : m.Return(result);
2852 : }
2853 :
2854 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2855 :
2856 : Handle<Map> maps[] = {
2857 : handle(ReadOnlyRoots(isolate).tuple3_map(), isolate),
2858 : handle(ReadOnlyRoots(isolate).tuple2_map(), isolate),
2859 10 : };
2860 :
2861 : {
2862 15 : for (size_t i = 0; i < 2; i++) {
2863 10 : Handle<Map> map = maps[i];
2864 : Handle<Struct> result =
2865 20 : Handle<Struct>::cast(ft.Call(map).ToHandleChecked());
2866 30 : CHECK_EQ(result->map(), *map);
2867 : #ifdef VERIFY_HEAP
2868 : isolate->heap()->Verify();
2869 : #endif
2870 : }
2871 5 : }
2872 5 : }
2873 :
2874 28342 : TEST(GotoIfNotWhiteSpaceOrLineTerminator) {
2875 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2876 :
2877 : const int kNumParams = 1;
2878 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2879 : StringTrimAssembler m(asm_tester.state());
2880 :
2881 : { // Returns true if whitespace, false otherwise.
2882 : Label if_not_whitespace(&m);
2883 :
2884 10 : m.GotoIfNotWhiteSpaceOrLineTerminator(m.SmiToInt32(m.Parameter(0)),
2885 10 : &if_not_whitespace);
2886 10 : m.Return(m.TrueConstant());
2887 :
2888 5 : m.BIND(&if_not_whitespace);
2889 10 : m.Return(m.FalseConstant());
2890 : }
2891 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2892 :
2893 5 : Handle<Object> true_value = ft.true_value();
2894 5 : Handle<Object> false_value = ft.false_value();
2895 :
2896 327680 : for (uc16 c = 0; c < 0xFFFF; c++) {
2897 : Handle<Object> expected_value =
2898 655350 : IsWhiteSpaceOrLineTerminator(c) ? true_value : false_value;
2899 327675 : ft.CheckCall(expected_value, handle(Smi::FromInt(c), isolate));
2900 5 : }
2901 5 : }
2902 :
2903 28342 : TEST(BranchIfNumberRelationalComparison) {
2904 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2905 : Factory* f = isolate->factory();
2906 : const int kNumParams = 2;
2907 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2908 : {
2909 5 : CodeStubAssembler m(asm_tester.state());
2910 5 : Label return_true(&m), return_false(&m);
2911 : m.BranchIfNumberRelationalComparison(Operation::kGreaterThanOrEqual,
2912 : m.Parameter(0), m.Parameter(1),
2913 5 : &return_true, &return_false);
2914 5 : m.BIND(&return_true);
2915 10 : m.Return(m.BooleanConstant(true));
2916 5 : m.BIND(&return_false);
2917 10 : m.Return(m.BooleanConstant(false));
2918 : }
2919 :
2920 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2921 :
2922 5 : ft.CheckTrue(f->NewNumber(0), f->NewNumber(0));
2923 5 : ft.CheckTrue(f->NewNumber(1), f->NewNumber(0));
2924 5 : ft.CheckTrue(f->NewNumber(1), f->NewNumber(1));
2925 5 : ft.CheckFalse(f->NewNumber(0), f->NewNumber(1));
2926 5 : ft.CheckFalse(f->NewNumber(-1), f->NewNumber(0));
2927 5 : ft.CheckTrue(f->NewNumber(-1), f->NewNumber(-1));
2928 :
2929 5 : ft.CheckTrue(f->NewNumber(-1), f->NewNumber(-1.5));
2930 5 : ft.CheckFalse(f->NewNumber(-1.5), f->NewNumber(-1));
2931 10 : ft.CheckTrue(f->NewNumber(-1.5), f->NewNumber(-1.5));
2932 5 : }
2933 :
2934 28342 : TEST(IsNumberArrayIndex) {
2935 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2936 : const int kNumParams = 1;
2937 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
2938 : {
2939 5 : CodeStubAssembler m(asm_tester.state());
2940 5 : TNode<Number> number = m.CAST(m.Parameter(0));
2941 : m.Return(
2942 15 : m.SmiFromInt32(m.UncheckedCast<Int32T>(m.IsNumberArrayIndex(number))));
2943 : }
2944 :
2945 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
2946 :
2947 : double indices[] = {Smi::kMinValue,
2948 : -11,
2949 : -1,
2950 : 0,
2951 : 1,
2952 : 2,
2953 : Smi::kMaxValue,
2954 : -11.0,
2955 : -11.1,
2956 : -2.0,
2957 : -1.0,
2958 : -0.0,
2959 : 0.0,
2960 : 0.00001,
2961 : 0.1,
2962 : 1,
2963 : 2,
2964 : Smi::kMinValue - 1.0,
2965 : Smi::kMinValue + 1.0,
2966 : Smi::kMinValue + 1.2,
2967 : kMaxInt + 1.2,
2968 : kMaxInt - 10.0,
2969 : kMaxInt - 1.0,
2970 : kMaxInt,
2971 : kMaxInt + 1.0,
2972 5 : kMaxInt + 10.0};
2973 :
2974 135 : for (size_t i = 0; i < arraysize(indices); i++) {
2975 130 : Handle<Object> index = isolate->factory()->NewNumber(indices[i]);
2976 : uint32_t array_index;
2977 520 : CHECK_EQ(index->ToArrayIndex(&array_index),
2978 : (ft.CallChecked<Smi>(index)->value() == 1));
2979 5 : }
2980 5 : }
2981 :
2982 28342 : TEST(NumberMinMax) {
2983 5 : Isolate* isolate(CcTest::InitIsolateOnce());
2984 : const int kNumParams = 2;
2985 5 : CodeAssemblerTester asm_tester_min(isolate, kNumParams);
2986 : {
2987 5 : CodeStubAssembler m(asm_tester_min.state());
2988 20 : m.Return(m.NumberMin(m.Parameter(0), m.Parameter(1)));
2989 : }
2990 5 : FunctionTester ft_min(asm_tester_min.GenerateCode(), kNumParams);
2991 :
2992 10 : CodeAssemblerTester asm_tester_max(isolate, kNumParams);
2993 : {
2994 5 : CodeStubAssembler m(asm_tester_max.state());
2995 20 : m.Return(m.NumberMax(m.Parameter(0), m.Parameter(1)));
2996 : }
2997 5 : FunctionTester ft_max(asm_tester_max.GenerateCode(), kNumParams);
2998 :
2999 : // Test smi values.
3000 : Handle<Smi> smi_1(Smi::FromInt(1), isolate);
3001 : Handle<Smi> smi_2(Smi::FromInt(2), isolate);
3002 : Handle<Smi> smi_5(Smi::FromInt(5), isolate);
3003 10 : CHECK_EQ(ft_min.CallChecked<Smi>(smi_1, smi_2)->value(), 1);
3004 10 : CHECK_EQ(ft_min.CallChecked<Smi>(smi_2, smi_1)->value(), 1);
3005 10 : CHECK_EQ(ft_max.CallChecked<Smi>(smi_1, smi_2)->value(), 2);
3006 10 : CHECK_EQ(ft_max.CallChecked<Smi>(smi_2, smi_1)->value(), 2);
3007 :
3008 : // Test double values.
3009 5 : Handle<Object> double_a = isolate->factory()->NewNumber(2.5);
3010 5 : Handle<Object> double_b = isolate->factory()->NewNumber(3.5);
3011 : Handle<Object> nan =
3012 5 : isolate->factory()->NewNumber(std::numeric_limits<double>::quiet_NaN());
3013 5 : Handle<Object> infinity = isolate->factory()->NewNumber(V8_INFINITY);
3014 :
3015 10 : CHECK_EQ(ft_min.CallChecked<HeapNumber>(double_a, double_b)->value(), 2.5);
3016 10 : CHECK_EQ(ft_min.CallChecked<HeapNumber>(double_b, double_a)->value(), 2.5);
3017 10 : CHECK_EQ(ft_min.CallChecked<HeapNumber>(infinity, double_a)->value(), 2.5);
3018 10 : CHECK_EQ(ft_min.CallChecked<HeapNumber>(double_a, infinity)->value(), 2.5);
3019 10 : CHECK(std::isnan(ft_min.CallChecked<HeapNumber>(nan, double_a)->value()));
3020 10 : CHECK(std::isnan(ft_min.CallChecked<HeapNumber>(double_a, nan)->value()));
3021 :
3022 10 : CHECK_EQ(ft_max.CallChecked<HeapNumber>(double_a, double_b)->value(), 3.5);
3023 10 : CHECK_EQ(ft_max.CallChecked<HeapNumber>(double_b, double_a)->value(), 3.5);
3024 10 : CHECK_EQ(ft_max.CallChecked<HeapNumber>(infinity, double_a)->value(),
3025 : V8_INFINITY);
3026 10 : CHECK_EQ(ft_max.CallChecked<HeapNumber>(double_a, infinity)->value(),
3027 : V8_INFINITY);
3028 10 : CHECK(std::isnan(ft_max.CallChecked<HeapNumber>(nan, double_a)->value()));
3029 10 : CHECK(std::isnan(ft_max.CallChecked<HeapNumber>(double_a, nan)->value()));
3030 :
3031 : // Mixed smi/double values.
3032 10 : CHECK_EQ(ft_max.CallChecked<HeapNumber>(smi_1, double_b)->value(), 3.5);
3033 10 : CHECK_EQ(ft_max.CallChecked<HeapNumber>(double_b, smi_1)->value(), 3.5);
3034 10 : CHECK_EQ(ft_min.CallChecked<HeapNumber>(smi_5, double_b)->value(), 3.5);
3035 15 : CHECK_EQ(ft_min.CallChecked<HeapNumber>(double_b, smi_5)->value(), 3.5);
3036 5 : }
3037 :
3038 28342 : TEST(NumberAddSub) {
3039 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3040 : const int kNumParams = 2;
3041 5 : CodeAssemblerTester asm_tester_add(isolate, kNumParams);
3042 : {
3043 5 : CodeStubAssembler m(asm_tester_add.state());
3044 20 : m.Return(m.NumberAdd(m.Parameter(0), m.Parameter(1)));
3045 : }
3046 5 : FunctionTester ft_add(asm_tester_add.GenerateCode(), kNumParams);
3047 :
3048 10 : CodeAssemblerTester asm_tester_sub(isolate, kNumParams);
3049 : {
3050 5 : CodeStubAssembler m(asm_tester_sub.state());
3051 20 : m.Return(m.NumberSub(m.Parameter(0), m.Parameter(1)));
3052 : }
3053 5 : FunctionTester ft_sub(asm_tester_sub.GenerateCode(), kNumParams);
3054 :
3055 : // Test smi values.
3056 : Handle<Smi> smi_1(Smi::FromInt(1), isolate);
3057 : Handle<Smi> smi_2(Smi::FromInt(2), isolate);
3058 10 : CHECK_EQ(ft_add.CallChecked<Smi>(smi_1, smi_2)->value(), 3);
3059 10 : CHECK_EQ(ft_sub.CallChecked<Smi>(smi_2, smi_1)->value(), 1);
3060 :
3061 : // Test double values.
3062 5 : Handle<Object> double_a = isolate->factory()->NewNumber(2.5);
3063 5 : Handle<Object> double_b = isolate->factory()->NewNumber(3.0);
3064 10 : CHECK_EQ(ft_add.CallChecked<HeapNumber>(double_a, double_b)->value(), 5.5);
3065 10 : CHECK_EQ(ft_sub.CallChecked<HeapNumber>(double_a, double_b)->value(), -.5);
3066 :
3067 : // Test overflow.
3068 : Handle<Smi> smi_max(Smi::FromInt(Smi::kMaxValue), isolate);
3069 : Handle<Smi> smi_min(Smi::FromInt(Smi::kMinValue), isolate);
3070 10 : CHECK_EQ(ft_add.CallChecked<HeapNumber>(smi_max, smi_1)->value(),
3071 : static_cast<double>(Smi::kMaxValue) + 1);
3072 10 : CHECK_EQ(ft_sub.CallChecked<HeapNumber>(smi_min, smi_1)->value(),
3073 : static_cast<double>(Smi::kMinValue) - 1);
3074 :
3075 : // Test mixed smi/double values.
3076 10 : CHECK_EQ(ft_add.CallChecked<HeapNumber>(smi_1, double_a)->value(), 3.5);
3077 10 : CHECK_EQ(ft_add.CallChecked<HeapNumber>(double_a, smi_1)->value(), 3.5);
3078 10 : CHECK_EQ(ft_sub.CallChecked<HeapNumber>(smi_1, double_a)->value(), -1.5);
3079 15 : CHECK_EQ(ft_sub.CallChecked<HeapNumber>(double_a, smi_1)->value(), 1.5);
3080 5 : }
3081 :
3082 28342 : TEST(CloneEmptyFixedArray) {
3083 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3084 : const int kNumParams = 1;
3085 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3086 : {
3087 5 : CodeStubAssembler m(asm_tester.state());
3088 10 : m.Return(m.CloneFixedArray(m.Parameter(0)));
3089 : }
3090 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3091 :
3092 5 : Handle<FixedArray> source(isolate->factory()->empty_fixed_array());
3093 10 : Handle<Object> result_raw = ft.Call(source).ToHandleChecked();
3094 : FixedArray result(FixedArray::cast(*result_raw));
3095 5 : CHECK_EQ(0, result->length());
3096 15 : CHECK_EQ(*(isolate->factory()->empty_fixed_array()), result);
3097 5 : }
3098 :
3099 28342 : TEST(CloneFixedArray) {
3100 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3101 : const int kNumParams = 1;
3102 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3103 : {
3104 5 : CodeStubAssembler m(asm_tester.state());
3105 10 : m.Return(m.CloneFixedArray(m.Parameter(0)));
3106 : }
3107 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3108 :
3109 5 : Handle<FixedArray> source(isolate->factory()->NewFixedArrayWithHoles(5));
3110 : source->set(1, Smi::FromInt(1234));
3111 10 : Handle<Object> result_raw = ft.Call(source).ToHandleChecked();
3112 : FixedArray result(FixedArray::cast(*result_raw));
3113 5 : CHECK_EQ(5, result->length());
3114 10 : CHECK(result->get(0)->IsTheHole(isolate));
3115 5 : CHECK_EQ(Smi::cast(result->get(1))->value(), 1234);
3116 10 : CHECK(result->get(2)->IsTheHole(isolate));
3117 10 : CHECK(result->get(3)->IsTheHole(isolate));
3118 15 : CHECK(result->get(4)->IsTheHole(isolate));
3119 5 : }
3120 :
3121 28342 : TEST(CloneFixedArrayCOW) {
3122 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3123 : const int kNumParams = 1;
3124 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3125 : {
3126 5 : CodeStubAssembler m(asm_tester.state());
3127 10 : m.Return(m.CloneFixedArray(m.Parameter(0)));
3128 : }
3129 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3130 :
3131 5 : Handle<FixedArray> source(isolate->factory()->NewFixedArrayWithHoles(5));
3132 : source->set(1, Smi::FromInt(1234));
3133 5 : source->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
3134 10 : Handle<Object> result_raw = ft.Call(source).ToHandleChecked();
3135 5 : FixedArray result(FixedArray::cast(*result_raw));
3136 15 : CHECK_EQ(*source, result);
3137 5 : }
3138 :
3139 28342 : TEST(ExtractFixedArrayCOWForceCopy) {
3140 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3141 : const int kNumParams = 1;
3142 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3143 : {
3144 5 : CodeStubAssembler m(asm_tester.state());
3145 : CodeStubAssembler::ExtractFixedArrayFlags flags;
3146 : flags |= CodeStubAssembler::ExtractFixedArrayFlag::kAllFixedArrays;
3147 : m.Return(m.ExtractFixedArray(m.Parameter(0), m.SmiConstant(0), nullptr,
3148 : nullptr, flags,
3149 15 : CodeStubAssembler::SMI_PARAMETERS));
3150 : }
3151 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3152 :
3153 5 : Handle<FixedArray> source(isolate->factory()->NewFixedArrayWithHoles(5));
3154 : source->set(1, Smi::FromInt(1234));
3155 5 : source->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
3156 10 : Handle<Object> result_raw = ft.Call(source).ToHandleChecked();
3157 : FixedArray result(FixedArray::cast(*result_raw));
3158 10 : CHECK_NE(*source, result);
3159 5 : CHECK_EQ(5, result->length());
3160 10 : CHECK(result->get(0)->IsTheHole(isolate));
3161 5 : CHECK_EQ(Smi::cast(result->get(1))->value(), 1234);
3162 10 : CHECK(result->get(2)->IsTheHole(isolate));
3163 10 : CHECK(result->get(3)->IsTheHole(isolate));
3164 15 : CHECK(result->get(4)->IsTheHole(isolate));
3165 5 : }
3166 :
3167 28342 : TEST(ExtractFixedArraySimple) {
3168 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3169 : const int kNumParams = 3;
3170 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3171 : {
3172 5 : CodeStubAssembler m(asm_tester.state());
3173 : CodeStubAssembler::ExtractFixedArrayFlags flags;
3174 : flags |= CodeStubAssembler::ExtractFixedArrayFlag::kAllFixedArrays;
3175 : flags |= CodeStubAssembler::ExtractFixedArrayFlag::kDontCopyCOW;
3176 : m.Return(m.ExtractFixedArray(m.Parameter(0), m.Parameter(1), m.Parameter(2),
3177 : nullptr, flags,
3178 10 : CodeStubAssembler::SMI_PARAMETERS));
3179 : }
3180 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3181 :
3182 5 : Handle<FixedArray> source(isolate->factory()->NewFixedArrayWithHoles(5));
3183 : source->set(1, Smi::FromInt(1234));
3184 : Handle<Object> result_raw =
3185 : ft.Call(source, Handle<Smi>(Smi::FromInt(1), isolate),
3186 5 : Handle<Smi>(Smi::FromInt(2), isolate))
3187 10 : .ToHandleChecked();
3188 : FixedArray result(FixedArray::cast(*result_raw));
3189 5 : CHECK_EQ(2, result->length());
3190 5 : CHECK_EQ(Smi::cast(result->get(0))->value(), 1234);
3191 15 : CHECK(result->get(1)->IsTheHole(isolate));
3192 5 : }
3193 :
3194 28342 : TEST(ExtractFixedArraySimpleSmiConstant) {
3195 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3196 : const int kNumParams = 1;
3197 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3198 : {
3199 5 : CodeStubAssembler m(asm_tester.state());
3200 : CodeStubAssembler::ExtractFixedArrayFlags flags;
3201 : flags |= CodeStubAssembler::ExtractFixedArrayFlag::kAllFixedArrays;
3202 : flags |= CodeStubAssembler::ExtractFixedArrayFlag::kDontCopyCOW;
3203 : m.Return(m.ExtractFixedArray(m.Parameter(0), m.SmiConstant(1),
3204 : m.SmiConstant(2), nullptr, flags,
3205 20 : CodeStubAssembler::SMI_PARAMETERS));
3206 : }
3207 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3208 :
3209 5 : Handle<FixedArray> source(isolate->factory()->NewFixedArrayWithHoles(5));
3210 : source->set(1, Smi::FromInt(1234));
3211 10 : Handle<Object> result_raw = ft.Call(source).ToHandleChecked();
3212 : FixedArray result(FixedArray::cast(*result_raw));
3213 5 : CHECK_EQ(2, result->length());
3214 5 : CHECK_EQ(Smi::cast(result->get(0))->value(), 1234);
3215 15 : CHECK(result->get(1)->IsTheHole(isolate));
3216 5 : }
3217 :
3218 28342 : TEST(ExtractFixedArraySimpleIntPtrConstant) {
3219 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3220 : const int kNumParams = 1;
3221 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3222 : {
3223 5 : CodeStubAssembler m(asm_tester.state());
3224 : CodeStubAssembler::ExtractFixedArrayFlags flags;
3225 : flags |= CodeStubAssembler::ExtractFixedArrayFlag::kAllFixedArrays;
3226 : flags |= CodeStubAssembler::ExtractFixedArrayFlag::kDontCopyCOW;
3227 : m.Return(m.ExtractFixedArray(m.Parameter(0), m.IntPtrConstant(1),
3228 : m.IntPtrConstant(2), nullptr, flags,
3229 20 : CodeStubAssembler::INTPTR_PARAMETERS));
3230 : }
3231 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3232 :
3233 5 : Handle<FixedArray> source(isolate->factory()->NewFixedArrayWithHoles(5));
3234 : source->set(1, Smi::FromInt(1234));
3235 10 : Handle<Object> result_raw = ft.Call(source).ToHandleChecked();
3236 : FixedArray result(FixedArray::cast(*result_raw));
3237 5 : CHECK_EQ(2, result->length());
3238 5 : CHECK_EQ(Smi::cast(result->get(0))->value(), 1234);
3239 15 : CHECK(result->get(1)->IsTheHole(isolate));
3240 5 : }
3241 :
3242 28342 : TEST(ExtractFixedArraySimpleIntPtrConstantNoDoubles) {
3243 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3244 : const int kNumParams = 1;
3245 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3246 : {
3247 5 : CodeStubAssembler m(asm_tester.state());
3248 : m.Return(m.ExtractFixedArray(
3249 : m.Parameter(0), m.IntPtrConstant(1), m.IntPtrConstant(2), nullptr,
3250 : CodeStubAssembler::ExtractFixedArrayFlag::kFixedArrays,
3251 20 : CodeStubAssembler::INTPTR_PARAMETERS));
3252 : }
3253 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3254 :
3255 5 : Handle<FixedArray> source(isolate->factory()->NewFixedArrayWithHoles(5));
3256 : source->set(1, Smi::FromInt(1234));
3257 10 : Handle<Object> result_raw = ft.Call(source).ToHandleChecked();
3258 : FixedArray result(FixedArray::cast(*result_raw));
3259 5 : CHECK_EQ(2, result->length());
3260 5 : CHECK_EQ(Smi::cast(result->get(0))->value(), 1234);
3261 15 : CHECK(result->get(1)->IsTheHole(isolate));
3262 5 : }
3263 :
3264 28342 : TEST(ExtractFixedArraySimpleIntPtrParameters) {
3265 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3266 : const int kNumParams = 3;
3267 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3268 : {
3269 5 : CodeStubAssembler m(asm_tester.state());
3270 15 : Node* p1_untagged = m.SmiUntag(m.Parameter(1));
3271 15 : Node* p2_untagged = m.SmiUntag(m.Parameter(2));
3272 10 : m.Return(m.ExtractFixedArray(m.Parameter(0), p1_untagged, p2_untagged));
3273 : }
3274 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3275 :
3276 5 : Handle<FixedArray> source(isolate->factory()->NewFixedArrayWithHoles(5));
3277 : source->set(1, Smi::FromInt(1234));
3278 : Handle<Object> result_raw =
3279 : ft.Call(source, Handle<Smi>(Smi::FromInt(1), isolate),
3280 5 : Handle<Smi>(Smi::FromInt(2), isolate))
3281 10 : .ToHandleChecked();
3282 : FixedArray result(FixedArray::cast(*result_raw));
3283 5 : CHECK_EQ(2, result->length());
3284 5 : CHECK_EQ(Smi::cast(result->get(0))->value(), 1234);
3285 10 : CHECK(result->get(1)->IsTheHole(isolate));
3286 :
3287 : Handle<FixedDoubleArray> source_double = Handle<FixedDoubleArray>::cast(
3288 5 : isolate->factory()->NewFixedDoubleArray(5));
3289 : source_double->set(0, 10);
3290 : source_double->set(1, 11);
3291 : source_double->set(2, 12);
3292 : source_double->set(3, 13);
3293 : source_double->set(4, 14);
3294 : Handle<Object> double_result_raw =
3295 : ft.Call(source_double, Handle<Smi>(Smi::FromInt(1), isolate),
3296 5 : Handle<Smi>(Smi::FromInt(2), isolate))
3297 10 : .ToHandleChecked();
3298 : FixedDoubleArray double_result = FixedDoubleArray::cast(*double_result_raw);
3299 5 : CHECK_EQ(2, double_result->length());
3300 5 : CHECK_EQ(double_result->get_scalar(0), 11);
3301 10 : CHECK_EQ(double_result->get_scalar(1), 12);
3302 5 : }
3303 :
3304 28342 : TEST(SingleInputPhiElimination) {
3305 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3306 : const int kNumParams = 2;
3307 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3308 : {
3309 5 : CodeStubAssembler m(asm_tester.state());
3310 10 : Variable temp1(&m, MachineRepresentation::kTagged);
3311 10 : Variable temp2(&m, MachineRepresentation::kTagged);
3312 15 : Label temp_label(&m, {&temp1, &temp2});
3313 15 : Label end_label(&m, {&temp1, &temp2});
3314 5 : temp1.Bind(m.Parameter(1));
3315 5 : temp2.Bind(m.Parameter(1));
3316 15 : m.Branch(m.WordEqual(m.Parameter(0), m.Parameter(1)), &end_label,
3317 10 : &temp_label);
3318 5 : temp1.Bind(m.Parameter(2));
3319 5 : temp2.Bind(m.Parameter(2));
3320 5 : m.BIND(&temp_label);
3321 5 : m.Goto(&end_label);
3322 5 : m.BIND(&end_label);
3323 10 : m.Return(temp1.value());
3324 : }
3325 10 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3326 : // Generating code without an assert is enough to make sure that the
3327 : // single-input phi is properly eliminated.
3328 5 : }
3329 :
3330 28342 : TEST(SmallOrderedHashMapAllocate) {
3331 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3332 : const int kNumParams = 1;
3333 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3334 : {
3335 5 : CodeStubAssembler m(asm_tester.state());
3336 5 : TNode<Smi> capacity = m.CAST(m.Parameter(0));
3337 : m.Return(m.AllocateSmallOrderedHashTable<SmallOrderedHashMap>(
3338 10 : m.SmiToIntPtr(capacity)));
3339 : }
3340 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3341 :
3342 : Factory* factory = isolate->factory();
3343 : int capacity = SmallOrderedHashMap::kMinCapacity;
3344 40 : while (capacity <= SmallOrderedHashMap::kMaxCapacity) {
3345 : Handle<SmallOrderedHashMap> expected =
3346 30 : factory->NewSmallOrderedHashMap(capacity);
3347 : Handle<Object> result_raw =
3348 60 : ft.Call(Handle<Smi>(Smi::FromInt(capacity), isolate)).ToHandleChecked();
3349 : Handle<SmallOrderedHashMap> actual = Handle<SmallOrderedHashMap>(
3350 : SmallOrderedHashMap::cast(*result_raw), isolate);
3351 30 : CHECK_EQ(capacity, actual->Capacity());
3352 30 : CHECK_EQ(0, actual->NumberOfElements());
3353 30 : CHECK_EQ(0, actual->NumberOfDeletedElements());
3354 30 : CHECK_EQ(capacity / SmallOrderedHashMap::kLoadFactor,
3355 : actual->NumberOfBuckets());
3356 90 : CHECK_EQ(0, memcmp(reinterpret_cast<void*>(expected->address()),
3357 : reinterpret_cast<void*>(actual->address()),
3358 : SmallOrderedHashMap::SizeFor(capacity)));
3359 : #ifdef VERIFY_HEAP
3360 : actual->SmallOrderedHashTableVerify(isolate);
3361 : #endif
3362 30 : capacity = capacity << 1;
3363 5 : }
3364 : #ifdef VERIFY_HEAP
3365 : isolate->heap()->Verify();
3366 : #endif
3367 5 : }
3368 :
3369 28342 : TEST(SmallOrderedHashSetAllocate) {
3370 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3371 : const int kNumParams = 1;
3372 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3373 : {
3374 5 : CodeStubAssembler m(asm_tester.state());
3375 5 : TNode<Smi> capacity = m.CAST(m.Parameter(0));
3376 : m.Return(m.AllocateSmallOrderedHashTable<SmallOrderedHashSet>(
3377 10 : m.SmiToIntPtr(capacity)));
3378 : }
3379 5 : FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
3380 :
3381 : int capacity = SmallOrderedHashSet::kMinCapacity;
3382 : Factory* factory = isolate->factory();
3383 40 : while (capacity <= SmallOrderedHashSet::kMaxCapacity) {
3384 : Handle<SmallOrderedHashSet> expected =
3385 30 : factory->NewSmallOrderedHashSet(capacity);
3386 : Handle<Object> result_raw =
3387 60 : ft.Call(Handle<Smi>(Smi::FromInt(capacity), isolate)).ToHandleChecked();
3388 : Handle<SmallOrderedHashSet> actual = Handle<SmallOrderedHashSet>(
3389 : SmallOrderedHashSet::cast(*result_raw), isolate);
3390 30 : CHECK_EQ(capacity, actual->Capacity());
3391 30 : CHECK_EQ(0, actual->NumberOfElements());
3392 30 : CHECK_EQ(0, actual->NumberOfDeletedElements());
3393 30 : CHECK_EQ(capacity / SmallOrderedHashSet::kLoadFactor,
3394 : actual->NumberOfBuckets());
3395 90 : CHECK_EQ(0, memcmp(reinterpret_cast<void*>(expected->address()),
3396 : reinterpret_cast<void*>(actual->address()),
3397 : SmallOrderedHashSet::SizeFor(capacity)));
3398 : #ifdef VERIFY_HEAP
3399 : actual->SmallOrderedHashTableVerify(isolate);
3400 : #endif
3401 30 : capacity = capacity << 1;
3402 5 : }
3403 : #ifdef VERIFY_HEAP
3404 : isolate->heap()->Verify();
3405 : #endif
3406 5 : }
3407 :
3408 28342 : TEST(IsDoubleElementsKind) {
3409 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3410 : const int kNumParams = 2;
3411 5 : CodeAssemblerTester ft_tester(isolate, kNumParams);
3412 : {
3413 5 : CodeStubAssembler m(ft_tester.state());
3414 : m.Return(m.SmiFromInt32(m.UncheckedCast<Int32T>(
3415 20 : m.IsDoubleElementsKind(m.SmiToInt32(m.Parameter(0))))));
3416 : }
3417 5 : FunctionTester ft(ft_tester.GenerateCode(), kNumParams);
3418 15 : CHECK_EQ(
3419 : (*Handle<Smi>::cast(
3420 : ft.Call(Handle<Smi>(Smi::FromInt(PACKED_DOUBLE_ELEMENTS), isolate))
3421 : .ToHandleChecked()))
3422 : ->value(),
3423 : 1);
3424 15 : CHECK_EQ(
3425 : (*Handle<Smi>::cast(
3426 : ft.Call(Handle<Smi>(Smi::FromInt(HOLEY_DOUBLE_ELEMENTS), isolate))
3427 : .ToHandleChecked()))
3428 : ->value(),
3429 : 1);
3430 15 : CHECK_EQ((*Handle<Smi>::cast(
3431 : ft.Call(Handle<Smi>(Smi::FromInt(HOLEY_ELEMENTS), isolate))
3432 : .ToHandleChecked()))
3433 : ->value(),
3434 : 0);
3435 15 : CHECK_EQ((*Handle<Smi>::cast(
3436 : ft.Call(Handle<Smi>(Smi::FromInt(PACKED_ELEMENTS), isolate))
3437 : .ToHandleChecked()))
3438 : ->value(),
3439 : 0);
3440 15 : CHECK_EQ((*Handle<Smi>::cast(
3441 : ft.Call(Handle<Smi>(Smi::FromInt(PACKED_SMI_ELEMENTS), isolate))
3442 : .ToHandleChecked()))
3443 : ->value(),
3444 : 0);
3445 15 : CHECK_EQ((*Handle<Smi>::cast(
3446 : ft.Call(Handle<Smi>(Smi::FromInt(HOLEY_SMI_ELEMENTS), isolate))
3447 : .ToHandleChecked()))
3448 : ->value(),
3449 : 0);
3450 15 : CHECK_EQ((*Handle<Smi>::cast(
3451 : ft.Call(Handle<Smi>(Smi::FromInt(DICTIONARY_ELEMENTS), isolate))
3452 : .ToHandleChecked()))
3453 : ->value(),
3454 5 : 0);
3455 5 : }
3456 :
3457 28342 : TEST(TestCallBuiltinInlineTrampoline) {
3458 5 : if (!i::FLAG_embedded_builtins) return;
3459 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3460 : const int kNumParams = 1;
3461 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3462 5 : CodeStubAssembler m(asm_tester.state());
3463 :
3464 : const int kContextOffset = 2;
3465 5 : Node* str = m.Parameter(0);
3466 5 : Node* context = m.Parameter(kNumParams + kContextOffset);
3467 :
3468 10 : Node* index = m.SmiConstant(2);
3469 :
3470 : m.Return(m.CallStub(Builtins::CallableFor(isolate, Builtins::kStringRepeat),
3471 15 : context, str, index));
3472 5 : AssemblerOptions options = AssemblerOptions::Default(isolate);
3473 5 : options.inline_offheap_trampolines = true;
3474 5 : options.use_pc_relative_calls_and_jumps = false;
3475 5 : options.isolate_independent_code = false;
3476 5 : FunctionTester ft(asm_tester.GenerateCode(options), kNumParams);
3477 5 : MaybeHandle<Object> result = ft.Call(MakeString("abcdef"));
3478 10 : CHECK(String::Equals(isolate, MakeString("abcdefabcdef"),
3479 5 : Handle<String>::cast(result.ToHandleChecked())));
3480 : }
3481 :
3482 28342 : TEST(TestCallBuiltinIndirectLoad) {
3483 5 : if (!i::FLAG_embedded_builtins) return;
3484 5 : Isolate* isolate(CcTest::InitIsolateOnce());
3485 : const int kNumParams = 1;
3486 5 : CodeAssemblerTester asm_tester(isolate, kNumParams);
3487 5 : CodeStubAssembler m(asm_tester.state());
3488 :
3489 : const int kContextOffset = 2;
3490 5 : Node* str = m.Parameter(0);
3491 5 : Node* context = m.Parameter(kNumParams + kContextOffset);
3492 :
3493 10 : Node* index = m.SmiConstant(2);
3494 :
3495 : m.Return(m.CallStub(Builtins::CallableFor(isolate, Builtins::kStringRepeat),
3496 15 : context, str, index));
3497 5 : AssemblerOptions options = AssemblerOptions::Default(isolate);
3498 5 : options.inline_offheap_trampolines = false;
3499 5 : options.use_pc_relative_calls_and_jumps = false;
3500 5 : options.isolate_independent_code = true;
3501 5 : FunctionTester ft(asm_tester.GenerateCode(options), kNumParams);
3502 5 : MaybeHandle<Object> result = ft.Call(MakeString("abcdef"));
3503 10 : CHECK(String::Equals(isolate, MakeString("abcdefabcdef"),
3504 5 : Handle<String>::cast(result.ToHandleChecked())));
3505 : }
3506 :
3507 28342 : TEST(TestGotoIfDebugExecutionModeChecksSideEffects) {
3508 20 : Isolate* isolate(CcTest::InitIsolateOnce());
3509 5 : CodeAssemblerTester asm_tester(isolate, 0);
3510 : {
3511 5 : CodeStubAssembler m(asm_tester.state());
3512 5 : Label is_true(&m), is_false(&m);
3513 5 : m.GotoIfDebugExecutionModeChecksSideEffects(&is_true);
3514 5 : m.Goto(&is_false);
3515 5 : m.BIND(&is_false);
3516 10 : m.Return(m.BooleanConstant(false));
3517 :
3518 5 : m.BIND(&is_true);
3519 10 : m.Return(m.BooleanConstant(true));
3520 : }
3521 :
3522 5 : FunctionTester ft(asm_tester.GenerateCode(), 0);
3523 :
3524 5 : CHECK(isolate->debug_execution_mode() != DebugInfo::kSideEffects);
3525 :
3526 10 : Handle<Object> result = ft.Call().ToHandleChecked();
3527 10 : CHECK(result->IsBoolean());
3528 10 : CHECK_EQ(false, result->BooleanValue(isolate));
3529 :
3530 5 : isolate->debug()->StartSideEffectCheckMode();
3531 5 : CHECK(isolate->debug_execution_mode() == DebugInfo::kSideEffects);
3532 :
3533 10 : result = ft.Call().ToHandleChecked();
3534 10 : CHECK(result->IsBoolean());
3535 10 : CHECK_EQ(true, result->BooleanValue(isolate));
3536 5 : }
3537 :
3538 : } // namespace compiler
3539 : } // namespace internal
3540 85011 : } // namespace v8
|