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 <limits> | 5 #include <limits> |
6 | 6 |
7 #include "src/compiler/control-builders.h" | 7 #include "src/compiler/control-builders.h" |
| 8 #include "src/compiler/generic-node-inl.h" |
8 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
9 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
10 #include "src/compiler/simplified-lowering.h" | 11 #include "src/compiler/simplified-lowering.h" |
11 #include "src/compiler/simplified-node-factory.h" | 12 #include "src/compiler/simplified-node-factory.h" |
12 #include "src/compiler/typer.h" | 13 #include "src/compiler/typer.h" |
13 #include "src/compiler/verifier.h" | 14 #include "src/compiler/verifier.h" |
14 #include "src/execution.h" | 15 #include "src/execution.h" |
15 #include "src/parser.h" | 16 #include "src/parser.h" |
16 #include "src/rewriter.h" | 17 #include "src/rewriter.h" |
17 #include "src/scopes.h" | 18 #include "src/scopes.h" |
18 #include "test/cctest/cctest.h" | 19 #include "test/cctest/cctest.h" |
19 #include "test/cctest/compiler/codegen-tester.h" | 20 #include "test/cctest/compiler/codegen-tester.h" |
20 #include "test/cctest/compiler/graph-builder-tester.h" | 21 #include "test/cctest/compiler/graph-builder-tester.h" |
21 #include "test/cctest/compiler/value-helper.h" | 22 #include "test/cctest/compiler/value-helper.h" |
22 | 23 |
23 using namespace v8::internal; | 24 using namespace v8::internal; |
24 using namespace v8::internal::compiler; | 25 using namespace v8::internal::compiler; |
25 | 26 |
| 27 // TODO(titzer): rename this to VMLoweringTester |
26 template <typename ReturnType> | 28 template <typename ReturnType> |
27 class SimplifiedGraphBuilderTester : public GraphBuilderTester<ReturnType> { | 29 class SimplifiedGraphBuilderTester : public GraphBuilderTester<ReturnType> { |
28 public: | 30 public: |
29 SimplifiedGraphBuilderTester(MachineRepresentation p0 = kMachineLast, | 31 SimplifiedGraphBuilderTester(MachineRepresentation p0 = kMachineLast, |
30 MachineRepresentation p1 = kMachineLast, | 32 MachineRepresentation p1 = kMachineLast, |
31 MachineRepresentation p2 = kMachineLast, | 33 MachineRepresentation p2 = kMachineLast, |
32 MachineRepresentation p3 = kMachineLast, | 34 MachineRepresentation p3 = kMachineLast, |
33 MachineRepresentation p4 = kMachineLast) | 35 MachineRepresentation p4 = kMachineLast) |
34 : GraphBuilderTester<ReturnType>(p0, p1, p2, p3, p4) {} | 36 : GraphBuilderTester<ReturnType>(p0, p1, p2, p3, p4), |
| 37 typer(this->zone()), |
| 38 source_positions(this->graph()), |
| 39 jsgraph(this->graph(), this->common(), &typer), |
| 40 lowering(&jsgraph, &source_positions) {} |
| 41 |
| 42 Typer typer; |
| 43 SourcePositionTable source_positions; |
| 44 JSGraph jsgraph; |
| 45 SimplifiedLowering lowering; |
35 | 46 |
36 // Close graph and lower one node. | 47 // Close graph and lower one node. |
37 void Lower(Node* node) { | 48 void Lower(Node* node) { |
38 this->End(); | 49 this->End(); |
39 Typer typer(this->zone()); | |
40 CommonOperatorBuilder common(this->zone()); | |
41 SourcePositionTable source_positions(this->graph()); | |
42 JSGraph jsgraph(this->graph(), &common, &typer); | |
43 SimplifiedLowering lowering(&jsgraph, &source_positions); | |
44 if (node == NULL) { | 50 if (node == NULL) { |
45 lowering.LowerAllNodes(); | 51 lowering.LowerAllNodes(); |
46 } else { | 52 } else { |
47 lowering.Lower(node); | 53 lowering.Lower(node); |
48 } | 54 } |
49 } | 55 } |
50 | 56 |
51 // Close graph and lower all nodes. | 57 // Close graph and lower all nodes. |
52 void LowerAllNodes() { Lower(NULL); } | 58 void LowerAllNodes() { Lower(NULL); } |
53 | 59 |
(...skipping 15 matching lines...) Expand all Loading... |
69 Node* LoadFloat64(double* ptr) { | 75 Node* LoadFloat64(double* ptr) { |
70 Node* ptr_node = this->PointerConstant(ptr); | 76 Node* ptr_node = this->PointerConstant(ptr); |
71 return this->Load(kMachineFloat64, ptr_node); | 77 return this->Load(kMachineFloat64, ptr_node); |
72 } | 78 } |
73 | 79 |
74 Factory* factory() { return this->isolate()->factory(); } | 80 Factory* factory() { return this->isolate()->factory(); } |
75 Heap* heap() { return this->isolate()->heap(); } | 81 Heap* heap() { return this->isolate()->heap(); } |
76 }; | 82 }; |
77 | 83 |
78 | 84 |
79 class SimplifiedGraphBuilderJSTester | |
80 : public SimplifiedGraphBuilderTester<Object*> { | |
81 public: | |
82 SimplifiedGraphBuilderJSTester() | |
83 : SimplifiedGraphBuilderTester<Object*>(), | |
84 f_(v8::Utils::OpenHandle(*v8::Handle<v8::Function>::Cast(CompileRun( | |
85 "(function() { 'use strict'; return 2.7123; })")))), | |
86 swapped_(false) { | |
87 set_current_context(HeapConstant(handle(f_->context()))); | |
88 } | |
89 | |
90 template <typename T> | |
91 T* CallJS() { | |
92 if (!swapped_) { | |
93 Compile(); | |
94 } | |
95 Handle<Object>* args = NULL; | |
96 MaybeHandle<Object> result = Execution::Call( | |
97 isolate(), f_, factory()->undefined_value(), 0, args, false); | |
98 return T::cast(*result.ToHandleChecked()); | |
99 } | |
100 | |
101 private: | |
102 void Compile() { | |
103 CompilationInfoWithZone info(f_); | |
104 CHECK(Parser::Parse(&info)); | |
105 StrictMode strict_mode = info.function()->strict_mode(); | |
106 info.SetStrictMode(strict_mode); | |
107 info.SetOptimizing(BailoutId::None(), Handle<Code>(f_->code())); | |
108 CHECK(Rewriter::Rewrite(&info)); | |
109 CHECK(Scope::Analyze(&info)); | |
110 CHECK_NE(NULL, info.scope()); | |
111 Pipeline pipeline(&info); | |
112 Linkage linkage(&info); | |
113 Handle<Code> code = pipeline.GenerateCodeForMachineGraph(&linkage, graph()); | |
114 CHECK(!code.is_null()); | |
115 f_->ReplaceCode(*code); | |
116 swapped_ = true; | |
117 } | |
118 | |
119 Handle<JSFunction> f_; | |
120 bool swapped_; | |
121 }; | |
122 | |
123 | |
124 TEST(RunChangeTaggedToInt32) { | |
125 SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged); | |
126 Node* x = t.ChangeTaggedToInt32(t.Parameter(0)); | |
127 t.Return(x); | |
128 | |
129 t.Lower(x); | |
130 | |
131 // TODO(titzer): remove me. | |
132 return; | |
133 | |
134 FOR_INT32_INPUTS(i) { | |
135 int32_t input = *i; | |
136 | |
137 if (Smi::IsValid(input)) { | |
138 int32_t result = t.Call(Smi::FromInt(input)); | |
139 CHECK_EQ(input, result); | |
140 } | |
141 | |
142 { | |
143 Handle<Object> number = t.factory()->NewNumber(input); | |
144 int32_t result = t.Call(*number); | |
145 CHECK_EQ(input, result); | |
146 } | |
147 | |
148 { | |
149 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); | |
150 int32_t result = t.Call(*number); | |
151 CHECK_EQ(input, result); | |
152 } | |
153 } | |
154 } | |
155 | |
156 | |
157 TEST(RunChangeTaggedToUint32) { | |
158 SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged); | |
159 Node* x = t.ChangeTaggedToUint32(t.Parameter(0)); | |
160 t.Return(x); | |
161 | |
162 t.Lower(x); | |
163 | |
164 // TODO(titzer): remove me. | |
165 return; | |
166 | |
167 FOR_UINT32_INPUTS(i) { | |
168 uint32_t input = *i; | |
169 | |
170 if (Smi::IsValid(input)) { | |
171 int32_t result = t.Call(Smi::FromInt(input)); | |
172 CHECK_EQ(static_cast<int32_t>(input), result); | |
173 } | |
174 | |
175 { | |
176 Handle<Object> number = t.factory()->NewNumber(input); | |
177 int32_t result = t.Call(*number); | |
178 CHECK_EQ(static_cast<int32_t>(input), result); | |
179 } | |
180 | |
181 { | |
182 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); | |
183 int32_t result = t.Call(*number); | |
184 CHECK_EQ(static_cast<int32_t>(input), result); | |
185 } | |
186 } | |
187 } | |
188 | |
189 | |
190 TEST(RunChangeTaggedToFloat64) { | |
191 SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged); | |
192 double result; | |
193 Node* x = t.ChangeTaggedToFloat64(t.Parameter(0)); | |
194 t.StoreFloat64(x, &result); | |
195 t.Return(t.Int32Constant(0)); | |
196 | |
197 t.Lower(x); | |
198 | |
199 // TODO(titzer): remove me. | |
200 return; | |
201 | |
202 { | |
203 FOR_INT32_INPUTS(i) { | |
204 int32_t input = *i; | |
205 | |
206 if (Smi::IsValid(input)) { | |
207 t.Call(Smi::FromInt(input)); | |
208 CHECK_EQ(input, static_cast<int32_t>(result)); | |
209 } | |
210 | |
211 { | |
212 Handle<Object> number = t.factory()->NewNumber(input); | |
213 t.Call(*number); | |
214 CHECK_EQ(input, static_cast<int32_t>(result)); | |
215 } | |
216 | |
217 { | |
218 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); | |
219 t.Call(*number); | |
220 CHECK_EQ(input, static_cast<int32_t>(result)); | |
221 } | |
222 } | |
223 } | |
224 | |
225 { | |
226 FOR_FLOAT64_INPUTS(i) { | |
227 double input = *i; | |
228 { | |
229 Handle<Object> number = t.factory()->NewNumber(input); | |
230 t.Call(*number); | |
231 CHECK_EQ(input, result); | |
232 } | |
233 | |
234 { | |
235 Handle<HeapNumber> number = t.factory()->NewHeapNumber(input); | |
236 t.Call(*number); | |
237 CHECK_EQ(input, result); | |
238 } | |
239 } | |
240 } | |
241 } | |
242 | |
243 | |
244 TEST(RunChangeBoolToBit) { | |
245 SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged); | |
246 Node* x = t.ChangeBoolToBit(t.Parameter(0)); | |
247 t.Return(x); | |
248 | |
249 t.Lower(x); | |
250 | |
251 if (!Pipeline::SupportedTarget()) return; | |
252 | |
253 { | |
254 Object* true_obj = t.heap()->true_value(); | |
255 int32_t result = t.Call(true_obj); | |
256 CHECK_EQ(1, result); | |
257 } | |
258 | |
259 { | |
260 Object* false_obj = t.heap()->false_value(); | |
261 int32_t result = t.Call(false_obj); | |
262 CHECK_EQ(0, result); | |
263 } | |
264 } | |
265 | |
266 | |
267 TEST(RunChangeBitToBool) { | |
268 SimplifiedGraphBuilderTester<Object*> t(kMachineTagged); | |
269 Node* x = t.ChangeBitToBool(t.Parameter(0)); | |
270 t.Return(x); | |
271 | |
272 t.Lower(x); | |
273 | |
274 // TODO(titzer): remove me. | |
275 return; | |
276 | |
277 { | |
278 Object* result = t.Call(1); | |
279 Object* true_obj = t.heap()->true_value(); | |
280 CHECK_EQ(true_obj, result); | |
281 } | |
282 | |
283 { | |
284 Object* result = t.Call(0); | |
285 Object* false_obj = t.heap()->false_value(); | |
286 CHECK_EQ(false_obj, result); | |
287 } | |
288 } | |
289 | |
290 | |
291 TEST(RunChangeInt32ToTagged) { | |
292 SimplifiedGraphBuilderJSTester t; | |
293 int32_t input; | |
294 Node* load = t.LoadInt32(&input); | |
295 Node* x = t.ChangeInt32ToTagged(load); | |
296 t.Return(x); | |
297 | |
298 t.Lower(x); | |
299 | |
300 // TODO(titzer): remove me. | |
301 return; | |
302 | |
303 | |
304 { | |
305 FOR_INT32_INPUTS(i) { | |
306 input = *i; | |
307 HeapNumber* result = t.CallJS<HeapNumber>(); | |
308 CHECK_EQ(static_cast<double>(input), result->value()); | |
309 } | |
310 } | |
311 | |
312 { | |
313 FOR_INT32_INPUTS(i) { | |
314 input = *i; | |
315 SimulateFullSpace(CcTest::heap()->new_space()); | |
316 HeapNumber* result = t.CallJS<HeapNumber>(); | |
317 CHECK_EQ(static_cast<double>(input), result->value()); | |
318 } | |
319 } | |
320 } | |
321 | |
322 | |
323 TEST(RunChangeUint32ToTagged) { | |
324 SimplifiedGraphBuilderJSTester t; | |
325 uint32_t input; | |
326 Node* load = t.LoadUint32(&input); | |
327 Node* x = t.ChangeUint32ToTagged(load); | |
328 t.Return(x); | |
329 | |
330 t.Lower(x); | |
331 | |
332 // TODO(titzer): remove me. | |
333 return; | |
334 | |
335 { | |
336 FOR_UINT32_INPUTS(i) { | |
337 input = *i; | |
338 HeapNumber* result = t.CallJS<HeapNumber>(); | |
339 double expected = static_cast<double>(input); | |
340 CHECK_EQ(expected, result->value()); | |
341 } | |
342 } | |
343 | |
344 { | |
345 FOR_UINT32_INPUTS(i) { | |
346 input = *i; | |
347 SimulateFullSpace(CcTest::heap()->new_space()); | |
348 HeapNumber* result = t.CallJS<HeapNumber>(); | |
349 double expected = static_cast<double>(static_cast<uint32_t>(input)); | |
350 CHECK_EQ(expected, result->value()); | |
351 } | |
352 } | |
353 } | |
354 | |
355 | |
356 TEST(RunChangeFloat64ToTagged) { | |
357 SimplifiedGraphBuilderJSTester t; | |
358 double input; | |
359 Node* load = t.LoadFloat64(&input); | |
360 Node* x = t.ChangeFloat64ToTagged(load); | |
361 t.Return(x); | |
362 | |
363 t.Lower(x); | |
364 | |
365 // TODO(titzer): remove me. | |
366 return; | |
367 | |
368 { | |
369 FOR_FLOAT64_INPUTS(i) { | |
370 input = *i; | |
371 HeapNumber* result = t.CallJS<HeapNumber>(); | |
372 CHECK_EQ(input, result->value()); | |
373 } | |
374 } | |
375 { | |
376 FOR_FLOAT64_INPUTS(i) { | |
377 input = *i; | |
378 SimulateFullSpace(CcTest::heap()->new_space()); | |
379 HeapNumber* result = t.CallJS<HeapNumber>(); | |
380 CHECK_EQ(input, result->value()); | |
381 } | |
382 } | |
383 } | |
384 | |
385 | |
386 // TODO(dcarney): find a home for these functions. | 85 // TODO(dcarney): find a home for these functions. |
387 namespace { | 86 namespace { |
388 | 87 |
389 FieldAccess ForJSObjectMap() { | 88 FieldAccess ForJSObjectMap() { |
390 FieldAccess access = {JSObject::kMapOffset, Handle<Name>(), Type::Any(), | 89 FieldAccess access = {JSObject::kMapOffset, Handle<Name>(), Type::Any(), |
391 kMachineTagged}; | 90 kMachineTagged}; |
392 return access; | 91 return access; |
393 } | 92 } |
394 | 93 |
395 | 94 |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 src->set(i, *TestObject()); | 304 src->set(i, *TestObject()); |
606 src_copy->set(i, src->get(i)); | 305 src_copy->set(i, src->get(i)); |
607 dst->set(i, *TestObject()); | 306 dst->set(i, *TestObject()); |
608 CHECK_NE(src_copy->get(i), dst->get(i)); | 307 CHECK_NE(src_copy->get(i), dst->get(i)); |
609 } | 308 } |
610 CHECK_EQ(kArraySize, t.Call(*src, *dst)); | 309 CHECK_EQ(kArraySize, t.Call(*src, *dst)); |
611 for (int i = 0; i < kArraySize; i++) { | 310 for (int i = 0; i < kArraySize; i++) { |
612 CHECK_EQ(src_copy->get(i), dst->get(i)); | 311 CHECK_EQ(src_copy->get(i), dst->get(i)); |
613 } | 312 } |
614 } | 313 } |
OLD | NEW |