OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
| 5 #include <cmath> |
| 6 |
5 #include "src/api.h" | 7 #include "src/api.h" |
6 #include "src/base/utils/random-number-generator.h" | 8 #include "src/base/utils/random-number-generator.h" |
7 #include "src/builtins/builtins-promise-gen.h" | 9 #include "src/builtins/builtins-promise-gen.h" |
8 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
9 #include "src/code-stub-assembler.h" | 11 #include "src/code-stub-assembler.h" |
10 #include "src/compiler/node.h" | 12 #include "src/compiler/node.h" |
11 #include "src/debug/debug.h" | 13 #include "src/debug/debug.h" |
12 #include "src/isolate.h" | 14 #include "src/isolate.h" |
13 #include "src/objects-inl.h" | 15 #include "src/objects-inl.h" |
14 #include "test/cctest/compiler/code-assembler-tester.h" | 16 #include "test/cctest/compiler/code-assembler-tester.h" |
15 #include "test/cctest/compiler/function-tester.h" | 17 #include "test/cctest/compiler/function-tester.h" |
16 | 18 |
17 namespace v8 { | 19 namespace v8 { |
18 namespace internal { | 20 namespace internal { |
19 | 21 |
20 using compiler::CodeAssemblerTester; | 22 using compiler::CodeAssemblerTester; |
21 using compiler::FunctionTester; | 23 using compiler::FunctionTester; |
22 using compiler::Node; | 24 using compiler::Node; |
23 using compiler::CodeAssemblerLabel; | 25 using compiler::CodeAssemblerLabel; |
24 using compiler::CodeAssemblerVariable; | 26 using compiler::CodeAssemblerVariable; |
25 using compiler::CodeAssemblerVariableList; | 27 using compiler::CodeAssemblerVariableList; |
26 | 28 |
| 29 namespace { |
| 30 |
| 31 void CheckToUint32Result(uint32_t expected, Handle<Object> result) { |
| 32 const int64_t result_int64 = NumberToInt64(*result); |
| 33 const uint32_t result_uint32 = NumberToUint32(*result); |
| 34 |
| 35 CHECK_EQ(static_cast<int64_t>(result_uint32), result_int64); |
| 36 CHECK_EQ(expected, result_uint32); |
| 37 |
| 38 // Ensure that the result is normalized to a Smi, i.e. a HeapNumber is only |
| 39 // returned if the result is not within Smi range. |
| 40 const bool expected_fits_into_intptr = |
| 41 static_cast<int64_t>(expected) <= |
| 42 static_cast<int64_t>(std::numeric_limits<intptr_t>::max()); |
| 43 if (expected_fits_into_intptr && |
| 44 Smi::IsValid(static_cast<intptr_t>(expected))) { |
| 45 CHECK(result->IsSmi()); |
| 46 } else { |
| 47 CHECK(result->IsHeapNumber()); |
| 48 } |
| 49 } |
| 50 |
| 51 } // namespace |
| 52 |
| 53 TEST(ToUint32) { |
| 54 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 55 Factory* factory = isolate->factory(); |
| 56 |
| 57 const int kNumParams = 1; |
| 58 CodeAssemblerTester data(isolate, kNumParams); |
| 59 CodeStubAssembler m(data.state()); |
| 60 |
| 61 const int kContextOffset = 2; |
| 62 Node* const context = m.Parameter(kNumParams + kContextOffset); |
| 63 Node* const input = m.Parameter(0); |
| 64 m.Return(m.ToUint32(context, input)); |
| 65 |
| 66 Handle<Code> code = data.GenerateCode(); |
| 67 FunctionTester ft(code, kNumParams); |
| 68 |
| 69 // clang-format off |
| 70 double inputs[] = { |
| 71 std::nan("-1"), std::nan("1"), std::nan("2"), |
| 72 -std::numeric_limits<double>::infinity(), |
| 73 std::numeric_limits<double>::infinity(), |
| 74 -0.0, -0.001, -0.5, -0.999, -1.0, |
| 75 0.0, 0.001, 0.5, 0.999, 1.0, |
| 76 -2147483647.9, -2147483648.0, -2147483648.5, -2147483648.9, // SmiMin. |
| 77 2147483646.9, 2147483647.0, 2147483647.5, 2147483647.9, // SmiMax. |
| 78 -4294967295.9, -4294967296.0, -4294967296.5, -4294967297.0, // - 2^32. |
| 79 4294967295.9, 4294967296.0, 4294967296.5, 4294967297.0, // 2^32. |
| 80 }; |
| 81 |
| 82 uint32_t expectations[] = { |
| 83 0, 0, 0, |
| 84 0, |
| 85 0, |
| 86 0, 0, 0, 0, 4294967295, |
| 87 0, 0, 0, 0, 1, |
| 88 2147483649, 2147483648, 2147483648, 2147483648, |
| 89 2147483646, 2147483647, 2147483647, 2147483647, |
| 90 1, 0, 0, 4294967295, |
| 91 4294967295, 0, 0, 1, |
| 92 }; |
| 93 // clang-format on |
| 94 |
| 95 STATIC_ASSERT(arraysize(inputs) == arraysize(expectations)); |
| 96 |
| 97 const int test_count = arraysize(inputs); |
| 98 for (int i = 0; i < test_count; i++) { |
| 99 Handle<Object> input_obj = factory->NewNumber(inputs[i]); |
| 100 Handle<HeapNumber> input_num; |
| 101 |
| 102 // Check with Smi input. |
| 103 if (input_obj->IsSmi()) { |
| 104 Handle<Smi> input_smi = Handle<Smi>::cast(input_obj); |
| 105 Handle<Object> result = ft.Call(input_smi).ToHandleChecked(); |
| 106 CheckToUint32Result(expectations[i], result); |
| 107 input_num = factory->NewHeapNumber(inputs[i]); |
| 108 } else { |
| 109 input_num = Handle<HeapNumber>::cast(input_obj); |
| 110 } |
| 111 |
| 112 // Check with HeapNumber input. |
| 113 { |
| 114 CHECK(input_num->IsHeapNumber()); |
| 115 Handle<Object> result = ft.Call(input_num).ToHandleChecked(); |
| 116 CheckToUint32Result(expectations[i], result); |
| 117 } |
| 118 } |
| 119 |
| 120 // A couple of final cases for ToNumber conversions. |
| 121 CheckToUint32Result(0, ft.Call(factory->undefined_value()).ToHandleChecked()); |
| 122 CheckToUint32Result(0, ft.Call(factory->null_value()).ToHandleChecked()); |
| 123 CheckToUint32Result(0, ft.Call(factory->false_value()).ToHandleChecked()); |
| 124 CheckToUint32Result(1, ft.Call(factory->true_value()).ToHandleChecked()); |
| 125 CheckToUint32Result( |
| 126 42, |
| 127 ft.Call(factory->NewStringFromAsciiChecked("0x2A")).ToHandleChecked()); |
| 128 |
| 129 ft.CheckThrows(factory->match_symbol()); |
| 130 } |
| 131 |
27 TEST(FixedArrayAccessSmiIndex) { | 132 TEST(FixedArrayAccessSmiIndex) { |
28 Isolate* isolate(CcTest::InitIsolateOnce()); | 133 Isolate* isolate(CcTest::InitIsolateOnce()); |
29 CodeAssemblerTester data(isolate); | 134 CodeAssemblerTester data(isolate); |
30 CodeStubAssembler m(data.state()); | 135 CodeStubAssembler m(data.state()); |
31 Handle<FixedArray> array = isolate->factory()->NewFixedArray(5); | 136 Handle<FixedArray> array = isolate->factory()->NewFixedArray(5); |
32 array->set(4, Smi::FromInt(733)); | 137 array->set(4, Smi::FromInt(733)); |
33 m.Return(m.LoadFixedArrayElement(m.HeapConstant(array), | 138 m.Return(m.LoadFixedArrayElement(m.HeapConstant(array), |
34 m.SmiTag(m.Int32Constant(4)), 0, | 139 m.SmiTag(m.Int32Constant(4)), 0, |
35 CodeStubAssembler::SMI_PARAMETERS)); | 140 CodeStubAssembler::SMI_PARAMETERS)); |
36 Handle<Code> code = data.GenerateCode(); | 141 Handle<Code> code = data.GenerateCode(); |
(...skipping 2459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2496 m.Return(m.SmiConstant(0)); | 2601 m.Return(m.SmiConstant(0)); |
2497 | 2602 |
2498 Handle<Code> code = data.GenerateCode(); | 2603 Handle<Code> code = data.GenerateCode(); |
2499 CHECK(!code.is_null()); | 2604 CHECK(!code.is_null()); |
2500 FunctionTester ft(code, kNumParams); | 2605 FunctionTester ft(code, kNumParams); |
2501 CHECK_EQ(1, Handle<Smi>::cast(ft.Call().ToHandleChecked())->value()); | 2606 CHECK_EQ(1, Handle<Smi>::cast(ft.Call().ToHandleChecked())->value()); |
2502 } | 2607 } |
2503 | 2608 |
2504 } // namespace internal | 2609 } // namespace internal |
2505 } // namespace v8 | 2610 } // namespace v8 |
OLD | NEW |