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 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_ | 5 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_ |
6 #define V8_COMPILER_REPRESENTATION_CHANGE_H_ | 6 #define V8_COMPILER_REPRESENTATION_CHANGE_H_ |
7 | 7 |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
11 #include "src/compiler/js-graph.h" | 11 #include "src/compiler/js-graph.h" |
12 #include "src/compiler/machine-operator.h" | 12 #include "src/compiler/machine-operator.h" |
13 #include "src/compiler/node-properties-inl.h" | 13 #include "src/compiler/node-properties-inl.h" |
14 #include "src/compiler/simplified-operator.h" | 14 #include "src/compiler/simplified-operator.h" |
15 | 15 |
16 namespace v8 { | 16 namespace v8 { |
17 namespace internal { | 17 namespace internal { |
18 namespace compiler { | 18 namespace compiler { |
19 | 19 |
20 // Contains logic related to changing the representation of values for constants | 20 // Contains logic related to changing the representation of values for constants |
21 // and other nodes, as well as lowering Simplified->Machine operators. | 21 // and other nodes, as well as lowering Simplified->Machine operators. |
22 // Eagerly folds any representation changes for constants. | 22 // Eagerly folds any representation changes for constants. |
23 class RepresentationChanger { | 23 class RepresentationChanger { |
24 public: | 24 public: |
25 RepresentationChanger(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified, | 25 RepresentationChanger(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified, |
26 Isolate* isolate) | 26 Isolate* isolate) |
27 : jsgraph_(jsgraph), | 27 : jsgraph_(jsgraph), |
28 simplified_(simplified), | 28 simplified_(simplified), |
29 isolate_(isolate), | 29 isolate_(isolate), |
30 bit_range_(Type::Range(isolate->factory()->NewNumber(0), | |
31 isolate->factory()->NewNumber(1), | |
32 jsgraph->zone())), | |
30 testing_type_errors_(false), | 33 testing_type_errors_(false), |
31 type_error_(false) {} | 34 type_error_(false) {} |
32 | 35 |
33 // TODO(titzer): should Word64 also be implicitly convertable to others? | 36 // TODO(titzer): should Word64 also be implicitly convertable to others? |
34 static const MachineTypeUnion rWord = | 37 static const MachineTypeUnion rWord = kRepWord8 | kRepWord16 | kRepWord32; |
35 kRepBit | kRepWord8 | kRepWord16 | kRepWord32; | |
36 | 38 |
37 Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type, | 39 Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type, |
38 MachineTypeUnion use_type) { | 40 MachineTypeUnion use_type) { |
39 if (!base::bits::IsPowerOfTwo32(output_type & kRepMask)) { | 41 if (!base::bits::IsPowerOfTwo32(output_type & kRepMask)) { |
40 // There should be only one output representation. | 42 // There should be only one output representation. |
41 return TypeError(node, output_type, use_type); | 43 return TypeError(node, output_type, use_type); |
42 } | 44 } |
43 if ((use_type & kRepMask) == (output_type & kRepMask)) { | 45 if ((use_type & kRepMask) == (output_type & kRepMask)) { |
44 // Representations are the same. That's a no-op. | 46 // Representations are the same. That's a no-op. |
45 return node; | 47 return node; |
(...skipping 209 matching lines...) Loading... | |
255 return node; // No change necessary. | 257 return node; // No change necessary. |
256 case IrOpcode::kFloat32Constant: | 258 case IrOpcode::kFloat32Constant: |
257 return MakeInt32Constant(OpParameter<float>(node)); | 259 return MakeInt32Constant(OpParameter<float>(node)); |
258 case IrOpcode::kNumberConstant: | 260 case IrOpcode::kNumberConstant: |
259 case IrOpcode::kFloat64Constant: | 261 case IrOpcode::kFloat64Constant: |
260 return MakeInt32Constant(OpParameter<double>(node)); | 262 return MakeInt32Constant(OpParameter<double>(node)); |
261 default: | 263 default: |
262 break; | 264 break; |
263 } | 265 } |
264 // Select the correct X -> Word32 operator. | 266 // Select the correct X -> Word32 operator. |
265 const Operator* op = NULL; | 267 const Operator* op; |
266 if (output_type & kRepFloat64) { | 268 if (output_type & kRepBit) { |
269 return node; // No change necessary. | |
270 } else if (output_type & kRepFloat64) { | |
267 if (output_type & kTypeUint32 || use_unsigned) { | 271 if (output_type & kTypeUint32 || use_unsigned) { |
268 op = machine()->ChangeFloat64ToUint32(); | 272 op = machine()->ChangeFloat64ToUint32(); |
269 } else { | 273 } else { |
270 op = machine()->ChangeFloat64ToInt32(); | 274 op = machine()->ChangeFloat64ToInt32(); |
271 } | 275 } |
272 } else if (output_type & kRepFloat32) { | 276 } else if (output_type & kRepFloat32) { |
273 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 | 277 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 |
274 if (output_type & kTypeUint32 || use_unsigned) { | 278 if (output_type & kTypeUint32 || use_unsigned) { |
275 op = machine()->ChangeFloat64ToUint32(); | 279 op = machine()->ChangeFloat64ToUint32(); |
276 } else { | 280 } else { |
(...skipping 14 matching lines...) Loading... | |
291 Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type) { | 295 Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type) { |
292 // Eagerly fold representation changes for constants. | 296 // Eagerly fold representation changes for constants. |
293 switch (node->opcode()) { | 297 switch (node->opcode()) { |
294 case IrOpcode::kInt32Constant: { | 298 case IrOpcode::kInt32Constant: { |
295 int32_t value = OpParameter<int32_t>(node); | 299 int32_t value = OpParameter<int32_t>(node); |
296 if (value == 0 || value == 1) return node; | 300 if (value == 0 || value == 1) return node; |
297 return jsgraph()->Int32Constant(1); // value != 0 | 301 return jsgraph()->Int32Constant(1); // value != 0 |
298 } | 302 } |
299 case IrOpcode::kNumberConstant: { | 303 case IrOpcode::kNumberConstant: { |
300 double value = OpParameter<double>(node); | 304 double value = OpParameter<double>(node); |
301 if (std::isnan(value) || value == 0.0) { | 305 if (value == 0.0 || value != value) return jsgraph()->Int32Constant(0); |
Jarin
2015/01/08 09:18:13
Just for my education: why is value != value bette
Benedikt Meurer
2015/01/08 09:20:01
It's not...
| |
302 return jsgraph()->Int32Constant(0); | 306 return jsgraph()->Int32Constant(1); // value != +0.0, -0.0, NaN |
303 } | |
304 return jsgraph()->Int32Constant(1); | |
305 } | 307 } |
306 case IrOpcode::kHeapConstant: { | 308 case IrOpcode::kHeapConstant: { |
307 Handle<Object> handle = OpParameter<Unique<Object> >(node).handle(); | 309 Handle<Object> object = OpParameter<Unique<Object>>(node).handle(); |
308 DCHECK(*handle == isolate()->heap()->true_value() || | 310 return jsgraph()->Int32Constant(object->BooleanValue() ? 1 : 0); |
309 *handle == isolate()->heap()->false_value()); | |
310 return jsgraph()->Int32Constant( | |
311 *handle == isolate()->heap()->true_value() ? 1 : 0); | |
312 } | 311 } |
313 default: | 312 default: |
314 break; | 313 break; |
315 } | 314 } |
316 // Select the correct X -> Bit operator. | 315 // Select the correct X -> Bit operator. |
317 const Operator* op; | 316 const Operator* op; |
318 if (output_type & rWord) { | 317 if (output_type & rWord) { |
319 return node; // No change necessary. | 318 op = simplified()->ChangeWord32ToBit(); |
320 } else if (output_type & kRepWord64) { | 319 } else if (output_type & kRepWord64) { |
321 return node; // TODO(titzer): No change necessary, on 64-bit. | 320 op = simplified()->ChangeWord64ToBit(); |
322 } else if (output_type & kRepTagged) { | 321 } else if (output_type & kRepTagged) { |
323 op = simplified()->ChangeBoolToBit(); | 322 Type* upper = NodeProperties::GetBounds(node).upper; |
323 if (upper->Is(Type::Boolean())) { | |
324 op = simplified()->ChangeBoolToBit(); | |
325 } else if (upper->Is(Type::Signed32())) { | |
326 // Tagged -> Int32 -> Bit | |
327 node = InsertChangeTaggedToInt32(node); | |
328 op = simplified()->ChangeWord32ToBit(); | |
329 } else if (upper->Is(Type::Unsigned32())) { | |
330 // Tagged -> Uint32 -> Bit | |
331 node = InsertChangeTaggedToUint32(node); | |
332 op = simplified()->ChangeWord32ToBit(); | |
333 } else { | |
334 return TypeError(node, output_type, kRepBit); | |
335 } | |
324 } else { | 336 } else { |
325 return TypeError(node, output_type, kRepBit); | 337 return TypeError(node, output_type, kRepBit); |
326 } | 338 } |
327 return jsgraph()->graph()->NewNode(op, node); | 339 return graph()->NewNode(op, node); |
328 } | 340 } |
329 | 341 |
330 Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type) { | 342 Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type) { |
331 if (output_type & kRepBit) { | 343 if (output_type & kRepBit) { |
332 return node; // Sloppy comparison -> word64 | 344 return node; // Sloppy comparison -> word64 |
333 } | 345 } |
334 // Can't really convert Word64 to anything else. Purported to be internal. | 346 // Can't really convert Word64 to anything else. Purported to be internal. |
335 return TypeError(node, output_type, kRepWord64); | 347 return TypeError(node, output_type, kRepWord64); |
336 } | 348 } |
337 | 349 |
(...skipping 84 matching lines...) Loading... | |
422 if (type->Is(Type::Unsigned32())) return kTypeUint32; | 434 if (type->Is(Type::Unsigned32())) return kTypeUint32; |
423 if (type->Is(Type::Number())) return kTypeNumber; | 435 if (type->Is(Type::Number())) return kTypeNumber; |
424 if (type->Is(Type::Boolean())) return kTypeBool; | 436 if (type->Is(Type::Boolean())) return kTypeBool; |
425 return kTypeAny; | 437 return kTypeAny; |
426 } | 438 } |
427 | 439 |
428 private: | 440 private: |
429 JSGraph* jsgraph_; | 441 JSGraph* jsgraph_; |
430 SimplifiedOperatorBuilder* simplified_; | 442 SimplifiedOperatorBuilder* simplified_; |
431 Isolate* isolate_; | 443 Isolate* isolate_; |
444 Type* bit_range_; | |
432 | 445 |
433 friend class RepresentationChangerTester; // accesses the below fields. | 446 friend class RepresentationChangerTester; // accesses the below fields. |
434 | 447 |
435 bool testing_type_errors_; // If {true}, don't abort on a type error. | 448 bool testing_type_errors_; // If {true}, don't abort on a type error. |
436 bool type_error_; // Set when a type error is detected. | 449 bool type_error_; // Set when a type error is detected. |
437 | 450 |
438 Node* TypeError(Node* node, MachineTypeUnion output_type, | 451 Node* TypeError(Node* node, MachineTypeUnion output_type, |
439 MachineTypeUnion use) { | 452 MachineTypeUnion use) { |
440 type_error_ = true; | 453 type_error_ = true; |
441 if (!testing_type_errors_) { | 454 if (!testing_type_errors_) { |
442 std::ostringstream out_str; | 455 std::ostringstream out_str; |
443 out_str << static_cast<MachineType>(output_type); | 456 out_str << static_cast<MachineType>(output_type); |
444 | 457 |
445 std::ostringstream use_str; | 458 std::ostringstream use_str; |
446 use_str << static_cast<MachineType>(use); | 459 use_str << static_cast<MachineType>(use); |
447 | 460 |
448 V8_Fatal(__FILE__, __LINE__, | 461 V8_Fatal(__FILE__, __LINE__, |
449 "RepresentationChangerError: node #%d:%s of " | 462 "RepresentationChangerError: node #%d:%s of " |
450 "%s cannot be changed to %s", | 463 "%s cannot be changed to %s", |
451 node->id(), node->op()->mnemonic(), out_str.str().c_str(), | 464 node->id(), node->op()->mnemonic(), out_str.str().c_str(), |
452 use_str.str().c_str()); | 465 use_str.str().c_str()); |
453 } | 466 } |
454 return node; | 467 return node; |
455 } | 468 } |
456 | 469 |
457 Node* InsertChangeFloat32ToFloat64(Node* node) { | 470 Node* InsertChangeFloat32ToFloat64(Node* node) { |
458 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), | 471 return graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node); |
459 node); | |
460 } | 472 } |
461 | 473 |
462 Node* InsertChangeTaggedToFloat64(Node* node) { | 474 Node* InsertChangeTaggedToFloat64(Node* node) { |
463 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), | 475 return graph()->NewNode(simplified()->ChangeTaggedToFloat64(), node); |
464 node); | |
465 } | 476 } |
466 | 477 |
467 JSGraph* jsgraph() { return jsgraph_; } | 478 Node* InsertChangeTaggedToInt32(Node* node) { |
468 Isolate* isolate() { return isolate_; } | 479 return graph()->NewNode(simplified()->ChangeTaggedToInt32(), node); |
469 SimplifiedOperatorBuilder* simplified() { return simplified_; } | 480 } |
470 MachineOperatorBuilder* machine() { return jsgraph()->machine(); } | 481 |
482 Node* InsertChangeTaggedToUint32(Node* node) { | |
483 return graph()->NewNode(simplified()->ChangeTaggedToUint32(), node); | |
484 } | |
485 | |
486 Graph* graph() const { return jsgraph()->graph(); } | |
487 JSGraph* jsgraph() const { return jsgraph_; } | |
488 Isolate* isolate() const { return isolate_; } | |
489 SimplifiedOperatorBuilder* simplified() const { return simplified_; } | |
490 MachineOperatorBuilder* machine() const { return jsgraph()->machine(); } | |
471 }; | 491 }; |
472 | 492 |
473 } // namespace compiler | 493 } // namespace compiler |
474 } // namespace internal | 494 } // namespace internal |
475 } // namespace v8 | 495 } // namespace v8 |
476 | 496 |
477 #endif // V8_COMPILER_REPRESENTATION_CHANGE_H_ | 497 #endif // V8_COMPILER_REPRESENTATION_CHANGE_H_ |
OLD | NEW |