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