| 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...) Expand 10 before | Expand all | Expand 10 after  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...) Expand all  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 || std::isnan(value)) return jsgraph()->Int32Constant(0); | 
| 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...) Expand 10 before | Expand all | Expand 10 after  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 | 
|---|