OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 "src/compiler/js-typed-lowering.h" | 5 #include "src/compiler/js-typed-lowering.h" |
6 #include "src/code-factory.h" | 6 #include "src/code-factory.h" |
7 #include "src/compilation-dependencies.h" | 7 #include "src/compilation-dependencies.h" |
8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/js-operator.h" | 10 #include "src/compiler/js-operator.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 namespace internal { | 26 namespace internal { |
27 namespace compiler { | 27 namespace compiler { |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 const ExternalArrayType kExternalArrayTypes[] = { | 31 const ExternalArrayType kExternalArrayTypes[] = { |
32 kExternalUint8Array, kExternalInt8Array, kExternalUint16Array, | 32 kExternalUint8Array, kExternalInt8Array, kExternalUint16Array, |
33 kExternalInt16Array, kExternalUint32Array, kExternalInt32Array, | 33 kExternalInt16Array, kExternalUint32Array, kExternalInt32Array, |
34 kExternalFloat32Array, kExternalFloat64Array}; | 34 kExternalFloat32Array, kExternalFloat64Array}; |
35 | 35 |
36 | |
37 const double kFloat64Values[] = { | |
38 -V8_INFINITY, -4.23878e+275, -5.82632e+265, -6.60355e+220, -6.26172e+212, | |
39 -2.56222e+211, -4.82408e+201, -1.84106e+157, -1.63662e+127, -1.55772e+100, | |
40 -1.67813e+72, -2.3382e+55, -3.179e+30, -1.441e+09, -1.0647e+09, | |
41 -7.99361e+08, -5.77375e+08, -2.20984e+08, -32757, -13171, -9970, -3984, | |
42 -107, -105, -92, -77, -61, -0.000208163, -1.86685e-06, -1.17296e-10, | |
43 -9.26358e-11, -5.08004e-60, -1.74753e-65, -1.06561e-71, -5.67879e-79, | |
44 -5.78459e-130, -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263, | |
45 -4.40497e-267, -2.19666e-273, -4.9998e-276, -5.59821e-278, -2.03855e-282, | |
46 -5.99335e-283, -7.17554e-284, -3.11744e-309, -0.0, 0.0, 2.22507e-308, | |
47 1.30127e-270, 7.62898e-260, 4.00313e-249, 3.16829e-233, 1.85244e-228, | |
48 2.03544e-129, 1.35126e-110, 1.01182e-106, 5.26333e-94, 1.35292e-90, | |
49 2.85394e-83, 1.78323e-77, 5.4967e-57, 1.03207e-25, 4.57401e-25, 1.58738e-05, | |
50 2, 125, 2310, 9636, 14802, 17168, 28945, 29305, 4.81336e+07, 1.41207e+08, | |
51 4.65962e+08, 1.40499e+09, 2.12648e+09, 8.80006e+30, 1.4446e+45, 1.12164e+54, | |
52 2.48188e+89, 6.71121e+102, 3.074e+112, 4.9699e+152, 5.58383e+166, | |
53 4.30654e+172, 7.08824e+185, 9.6586e+214, 2.028e+223, 6.63277e+243, | |
54 1.56192e+261, 1.23202e+269, 5.72883e+289, 8.5798e+290, 1.40256e+294, | |
55 1.79769e+308, V8_INFINITY}; | |
56 | |
57 | |
58 const size_t kIndices[] = {0, 1, 42, 100, 1024}; | 36 const size_t kIndices[] = {0, 1, 42, 100, 1024}; |
59 | 37 |
60 | |
61 const double kIntegerValues[] = {-V8_INFINITY, INT_MIN, -1000.0, -42.0, | |
62 -1.0, 0.0, 1.0, 42.0, | |
63 1000.0, INT_MAX, UINT_MAX, V8_INFINITY}; | |
64 | |
65 | |
66 Type* const kJSTypes[] = {Type::Undefined(), Type::Null(), Type::Boolean(), | 38 Type* const kJSTypes[] = {Type::Undefined(), Type::Null(), Type::Boolean(), |
67 Type::Number(), Type::String(), Type::Object()}; | 39 Type::Number(), Type::String(), Type::Object()}; |
68 | 40 |
69 STATIC_ASSERT(LANGUAGE_END == 2); | 41 STATIC_ASSERT(LANGUAGE_END == 2); |
70 const LanguageMode kLanguageModes[] = {SLOPPY, STRICT}; | 42 const LanguageMode kLanguageModes[] = {SLOPPY, STRICT}; |
71 | 43 |
72 } // namespace | 44 } // namespace |
73 | 45 |
74 | 46 |
75 class JSTypedLoweringTest : public TypedGraphTest { | 47 class JSTypedLoweringTest : public TypedGraphTest { |
(...skipping 29 matching lines...) Expand all Loading... |
105 | 77 |
106 JSOperatorBuilder* javascript() { return &javascript_; } | 78 JSOperatorBuilder* javascript() { return &javascript_; } |
107 | 79 |
108 private: | 80 private: |
109 JSOperatorBuilder javascript_; | 81 JSOperatorBuilder javascript_; |
110 CompilationDependencies deps_; | 82 CompilationDependencies deps_; |
111 }; | 83 }; |
112 | 84 |
113 | 85 |
114 // ----------------------------------------------------------------------------- | 86 // ----------------------------------------------------------------------------- |
115 // Constant propagation | |
116 | |
117 | |
118 TEST_F(JSTypedLoweringTest, ParameterWithMinusZero) { | |
119 { | |
120 Reduction r = Reduce( | |
121 Parameter(Type::Constant(factory()->minus_zero_value(), zone()))); | |
122 ASSERT_TRUE(r.Changed()); | |
123 EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0)); | |
124 } | |
125 { | |
126 Reduction r = Reduce(Parameter(Type::MinusZero())); | |
127 ASSERT_TRUE(r.Changed()); | |
128 EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0)); | |
129 } | |
130 { | |
131 Reduction r = Reduce(Parameter( | |
132 Type::Union(Type::MinusZero(), | |
133 Type::Constant(factory()->NewNumber(0), zone()), zone()))); | |
134 EXPECT_FALSE(r.Changed()); | |
135 } | |
136 } | |
137 | |
138 | |
139 TEST_F(JSTypedLoweringTest, ParameterWithNull) { | |
140 Handle<HeapObject> null = factory()->null_value(); | |
141 { | |
142 Reduction r = Reduce(Parameter(Type::Constant(null, zone()))); | |
143 ASSERT_TRUE(r.Changed()); | |
144 EXPECT_THAT(r.replacement(), IsHeapConstant(null)); | |
145 } | |
146 { | |
147 Reduction r = Reduce(Parameter(Type::Null())); | |
148 ASSERT_TRUE(r.Changed()); | |
149 EXPECT_THAT(r.replacement(), IsHeapConstant(null)); | |
150 } | |
151 } | |
152 | |
153 | |
154 TEST_F(JSTypedLoweringTest, ParameterWithNaN) { | |
155 const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(), | |
156 std::numeric_limits<double>::quiet_NaN(), | |
157 std::numeric_limits<double>::signaling_NaN()}; | |
158 TRACED_FOREACH(double, nan, kNaNs) { | |
159 Handle<Object> constant = factory()->NewNumber(nan); | |
160 Reduction r = Reduce(Parameter(Type::Constant(constant, zone()))); | |
161 ASSERT_TRUE(r.Changed()); | |
162 EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN())); | |
163 } | |
164 { | |
165 Reduction r = | |
166 Reduce(Parameter(Type::Constant(factory()->nan_value(), zone()))); | |
167 ASSERT_TRUE(r.Changed()); | |
168 EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN())); | |
169 } | |
170 { | |
171 Reduction r = Reduce(Parameter(Type::NaN())); | |
172 ASSERT_TRUE(r.Changed()); | |
173 EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN())); | |
174 } | |
175 } | |
176 | |
177 | |
178 TEST_F(JSTypedLoweringTest, ParameterWithPlainNumber) { | |
179 TRACED_FOREACH(double, value, kFloat64Values) { | |
180 Handle<Object> constant = factory()->NewNumber(value); | |
181 Reduction r = Reduce(Parameter(Type::Constant(constant, zone()))); | |
182 ASSERT_TRUE(r.Changed()); | |
183 EXPECT_THAT(r.replacement(), IsNumberConstant(value)); | |
184 } | |
185 TRACED_FOREACH(double, value, kIntegerValues) { | |
186 Reduction r = Reduce(Parameter(Type::Range(value, value, zone()))); | |
187 ASSERT_TRUE(r.Changed()); | |
188 EXPECT_THAT(r.replacement(), IsNumberConstant(value)); | |
189 } | |
190 } | |
191 | |
192 | |
193 TEST_F(JSTypedLoweringTest, ParameterWithUndefined) { | |
194 Handle<HeapObject> undefined = factory()->undefined_value(); | |
195 { | |
196 Reduction r = Reduce(Parameter(Type::Undefined())); | |
197 ASSERT_TRUE(r.Changed()); | |
198 EXPECT_THAT(r.replacement(), IsHeapConstant(undefined)); | |
199 } | |
200 { | |
201 Reduction r = Reduce(Parameter(Type::Constant(undefined, zone()))); | |
202 ASSERT_TRUE(r.Changed()); | |
203 EXPECT_THAT(r.replacement(), IsHeapConstant(undefined)); | |
204 } | |
205 } | |
206 | |
207 | |
208 // ----------------------------------------------------------------------------- | |
209 // JSToBoolean | 87 // JSToBoolean |
210 | 88 |
211 | 89 |
212 TEST_F(JSTypedLoweringTest, JSToBooleanWithBoolean) { | 90 TEST_F(JSTypedLoweringTest, JSToBooleanWithBoolean) { |
213 Node* input = Parameter(Type::Boolean(), 0); | 91 Node* input = Parameter(Type::Boolean(), 0); |
214 Node* context = Parameter(Type::Any(), 1); | 92 Node* context = Parameter(Type::Any(), 1); |
215 Reduction r = Reduce(graph()->NewNode( | 93 Reduction r = Reduce(graph()->NewNode( |
216 javascript()->ToBoolean(ToBooleanHint::kAny), input, context)); | 94 javascript()->ToBoolean(ToBooleanHint::kAny), input, context)); |
217 ASSERT_TRUE(r.Changed()); | 95 ASSERT_TRUE(r.Changed()); |
218 EXPECT_EQ(input, r.replacement()); | 96 EXPECT_EQ(input, r.replacement()); |
219 } | 97 } |
220 | 98 |
221 | 99 |
222 TEST_F(JSTypedLoweringTest, JSToBooleanWithFalsish) { | |
223 Node* input = Parameter( | |
224 Type::Union( | |
225 Type::MinusZero(), | |
226 Type::Union( | |
227 Type::NaN(), | |
228 Type::Union( | |
229 Type::Null(), | |
230 Type::Union( | |
231 Type::Undefined(), | |
232 Type::Union( | |
233 Type::Undetectable(), | |
234 Type::Union( | |
235 Type::Constant(factory()->false_value(), zone()), | |
236 Type::Range(0.0, 0.0, zone()), zone()), | |
237 zone()), | |
238 zone()), | |
239 zone()), | |
240 zone()), | |
241 zone()), | |
242 0); | |
243 Node* context = Parameter(Type::Any(), 1); | |
244 Reduction r = Reduce(graph()->NewNode( | |
245 javascript()->ToBoolean(ToBooleanHint::kAny), input, context)); | |
246 ASSERT_TRUE(r.Changed()); | |
247 EXPECT_THAT(r.replacement(), IsFalseConstant()); | |
248 } | |
249 | |
250 | |
251 TEST_F(JSTypedLoweringTest, JSToBooleanWithTruish) { | |
252 Node* input = Parameter( | |
253 Type::Union( | |
254 Type::Constant(factory()->true_value(), zone()), | |
255 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()), | |
256 zone()), | |
257 0); | |
258 Node* context = Parameter(Type::Any(), 1); | |
259 Reduction r = Reduce(graph()->NewNode( | |
260 javascript()->ToBoolean(ToBooleanHint::kAny), input, context)); | |
261 ASSERT_TRUE(r.Changed()); | |
262 EXPECT_THAT(r.replacement(), IsTrueConstant()); | |
263 } | |
264 | |
265 | |
266 TEST_F(JSTypedLoweringTest, JSToBooleanWithNonZeroPlainNumber) { | |
267 Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0); | |
268 Node* context = Parameter(Type::Any(), 1); | |
269 Reduction r = Reduce(graph()->NewNode( | |
270 javascript()->ToBoolean(ToBooleanHint::kAny), input, context)); | |
271 ASSERT_TRUE(r.Changed()); | |
272 EXPECT_THAT(r.replacement(), IsTrueConstant()); | |
273 } | |
274 | |
275 | |
276 TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumber) { | 100 TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumber) { |
277 Node* input = Parameter(Type::OrderedNumber(), 0); | 101 Node* input = Parameter(Type::OrderedNumber(), 0); |
278 Node* context = Parameter(Type::Any(), 1); | 102 Node* context = Parameter(Type::Any(), 1); |
279 Reduction r = Reduce(graph()->NewNode( | 103 Reduction r = Reduce(graph()->NewNode( |
280 javascript()->ToBoolean(ToBooleanHint::kAny), input, context)); | 104 javascript()->ToBoolean(ToBooleanHint::kAny), input, context)); |
281 ASSERT_TRUE(r.Changed()); | 105 ASSERT_TRUE(r.Changed()); |
282 EXPECT_THAT(r.replacement(), | 106 EXPECT_THAT(r.replacement(), |
283 IsBooleanNot(IsNumberEqual(input, IsNumberConstant(0.0)))); | 107 IsBooleanNot(IsNumberEqual(input, IsNumberConstant(0.0)))); |
284 } | 108 } |
285 | 109 |
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 EmptyFrameState(), effect, control)); | 1022 EmptyFrameState(), effect, control)); |
1199 ASSERT_TRUE(r.Changed()); | 1023 ASSERT_TRUE(r.Changed()); |
1200 EXPECT_THAT(r.replacement(), IsSpeculativeNumberBitwiseXor( | 1024 EXPECT_THAT(r.replacement(), IsSpeculativeNumberBitwiseXor( |
1201 NumberOperationHint::kNumberOrOddball, lhs, | 1025 NumberOperationHint::kNumberOrOddball, lhs, |
1202 rhs, effect, control)); | 1026 rhs, effect, control)); |
1203 } | 1027 } |
1204 | 1028 |
1205 } // namespace compiler | 1029 } // namespace compiler |
1206 } // namespace internal | 1030 } // namespace internal |
1207 } // namespace v8 | 1031 } // namespace v8 |
OLD | NEW |