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