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