| Index: src/compiler/representation-change.h
 | 
| diff --git a/src/compiler/representation-change.h b/src/compiler/representation-change.h
 | 
| index bd5fb5f79349b7abf95233f7bcf7d0111b98267a..8adab1ae461a8fb7270557adbb3d78ea1a8e9728 100644
 | 
| --- a/src/compiler/representation-change.h
 | 
| +++ b/src/compiler/representation-change.h
 | 
| @@ -14,50 +14,6 @@ namespace v8 {
 | 
|  namespace internal {
 | 
|  namespace compiler {
 | 
|  
 | 
| -// The types and representations tracked during representation inference
 | 
| -// and change insertion.
 | 
| -// TODO(titzer): First, merge MachineType and RepType.
 | 
| -// TODO(titzer): Second, Use the real type system instead of RepType.
 | 
| -enum RepType {
 | 
| -  // Representations.
 | 
| -  rBit = 1 << 0,
 | 
| -  rWord32 = 1 << 1,
 | 
| -  rWord64 = 1 << 2,
 | 
| -  rFloat64 = 1 << 3,
 | 
| -  rTagged = 1 << 4,
 | 
| -
 | 
| -  // Types.
 | 
| -  tBool = 1 << 5,
 | 
| -  tInt32 = 1 << 6,
 | 
| -  tUint32 = 1 << 7,
 | 
| -  tInt64 = 1 << 8,
 | 
| -  tUint64 = 1 << 9,
 | 
| -  tNumber = 1 << 10,
 | 
| -  tAny = 1 << 11
 | 
| -};
 | 
| -
 | 
| -#define REP_TYPE_STRLEN 24
 | 
| -
 | 
| -typedef uint16_t RepTypeUnion;
 | 
| -
 | 
| -
 | 
| -inline void RenderRepTypeUnion(char* buf, RepTypeUnion info) {
 | 
| -  base::OS::SNPrintF(buf, REP_TYPE_STRLEN, "{%s%s%s%s%s %s%s%s%s%s%s%s}",
 | 
| -                     (info & rBit) ? "k" : " ", (info & rWord32) ? "w" : " ",
 | 
| -                     (info & rWord64) ? "q" : " ",
 | 
| -                     (info & rFloat64) ? "f" : " ",
 | 
| -                     (info & rTagged) ? "t" : " ", (info & tBool) ? "Z" : " ",
 | 
| -                     (info & tInt32) ? "I" : " ", (info & tUint32) ? "U" : " ",
 | 
| -                     (info & tInt64) ? "L" : " ", (info & tUint64) ? "J" : " ",
 | 
| -                     (info & tNumber) ? "N" : " ", (info & tAny) ? "*" : " ");
 | 
| -}
 | 
| -
 | 
| -
 | 
| -const RepTypeUnion rMask = rBit | rWord32 | rWord64 | rFloat64 | rTagged;
 | 
| -const RepTypeUnion tMask =
 | 
| -    tBool | tInt32 | tUint32 | tInt64 | tUint64 | tNumber | tAny;
 | 
| -const RepType rPtr = kPointerSize == 4 ? rWord32 : rWord64;
 | 
| -
 | 
|  // Contains logic related to changing the representation of values for constants
 | 
|  // and other nodes, as well as lowering Simplified->Machine operators.
 | 
|  // Eagerly folds any representation changes for constants.
 | 
| @@ -72,50 +28,61 @@ class RepresentationChanger {
 | 
|          testing_type_errors_(false),
 | 
|          type_error_(false) {}
 | 
|  
 | 
| +  // TODO(titzer): should Word64 also be implicitly convertable to others?
 | 
| +  static const MachineTypeUnion rWord =
 | 
| +      kRepBit | kRepWord8 | kRepWord16 | kRepWord32;
 | 
|  
 | 
| -  Node* GetRepresentationFor(Node* node, RepTypeUnion output_type,
 | 
| -                             RepTypeUnion use_type) {
 | 
| -    if (!IsPowerOf2(output_type & rMask)) {
 | 
| +  Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type,
 | 
| +                             MachineTypeUnion use_type) {
 | 
| +    if (!IsPowerOf2(output_type & kRepMask)) {
 | 
|        // There should be only one output representation.
 | 
|        return TypeError(node, output_type, use_type);
 | 
|      }
 | 
| -    if ((use_type & rMask) == (output_type & rMask)) {
 | 
| +    if ((use_type & kRepMask) == (output_type & kRepMask)) {
 | 
|        // Representations are the same. That's a no-op.
 | 
|        return node;
 | 
|      }
 | 
| -    if (use_type & rTagged) {
 | 
| +    if ((use_type & rWord) && (output_type & rWord)) {
 | 
| +      // Both are words less than or equal to 32-bits.
 | 
| +      // Since loads of integers from memory implicitly sign or zero extend the
 | 
| +      // value to the full machine word size and stores implicitly truncate,
 | 
| +      // no representation change is necessary.
 | 
| +      return node;
 | 
| +    }
 | 
| +    if (use_type & kRepTagged) {
 | 
|        return GetTaggedRepresentationFor(node, output_type);
 | 
| -    } else if (use_type & rFloat64) {
 | 
| +    } else if (use_type & kRepFloat64) {
 | 
|        return GetFloat64RepresentationFor(node, output_type);
 | 
| -    } else if (use_type & rWord32) {
 | 
| -      return GetWord32RepresentationFor(node, output_type, use_type & tUint32);
 | 
| -    } else if (use_type & rBit) {
 | 
| +    } else if (use_type & kRepBit) {
 | 
|        return GetBitRepresentationFor(node, output_type);
 | 
| -    } else if (use_type & rWord64) {
 | 
| +    } else if (use_type & rWord) {
 | 
| +      return GetWord32RepresentationFor(node, output_type,
 | 
| +                                        use_type & kTypeUint32);
 | 
| +    } else if (use_type & kRepWord64) {
 | 
|        return GetWord64RepresentationFor(node, output_type);
 | 
|      } else {
 | 
|        return node;
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  Node* GetTaggedRepresentationFor(Node* node, RepTypeUnion output_type) {
 | 
| +  Node* GetTaggedRepresentationFor(Node* node, MachineTypeUnion output_type) {
 | 
|      // Eagerly fold representation changes for constants.
 | 
|      switch (node->opcode()) {
 | 
|        case IrOpcode::kNumberConstant:
 | 
|        case IrOpcode::kHeapConstant:
 | 
|          return node;  // No change necessary.
 | 
|        case IrOpcode::kInt32Constant:
 | 
| -        if (output_type & tUint32) {
 | 
| +        if (output_type & kTypeUint32) {
 | 
|            uint32_t value = ValueOf<uint32_t>(node->op());
 | 
|            return jsgraph()->Constant(static_cast<double>(value));
 | 
| -        } else if (output_type & tInt32) {
 | 
| +        } else if (output_type & kTypeInt32) {
 | 
|            int32_t value = ValueOf<int32_t>(node->op());
 | 
|            return jsgraph()->Constant(value);
 | 
| -        } else if (output_type & rBit) {
 | 
| +        } else if (output_type & kRepBit) {
 | 
|            return ValueOf<int32_t>(node->op()) == 0 ? jsgraph()->FalseConstant()
 | 
|                                                     : jsgraph()->TrueConstant();
 | 
|          } else {
 | 
| -          return TypeError(node, output_type, rTagged);
 | 
| +          return TypeError(node, output_type, kRepTagged);
 | 
|          }
 | 
|        case IrOpcode::kFloat64Constant:
 | 
|          return jsgraph()->Constant(ValueOf<double>(node->op()));
 | 
| @@ -124,31 +91,31 @@ class RepresentationChanger {
 | 
|      }
 | 
|      // Select the correct X -> Tagged operator.
 | 
|      Operator* op;
 | 
| -    if (output_type & rBit) {
 | 
| +    if (output_type & kRepBit) {
 | 
|        op = simplified()->ChangeBitToBool();
 | 
| -    } else if (output_type & rWord32) {
 | 
| -      if (output_type & tUint32) {
 | 
| +    } else if (output_type & rWord) {
 | 
| +      if (output_type & kTypeUint32) {
 | 
|          op = simplified()->ChangeUint32ToTagged();
 | 
| -      } else if (output_type & tInt32) {
 | 
| +      } else if (output_type & kTypeInt32) {
 | 
|          op = simplified()->ChangeInt32ToTagged();
 | 
|        } else {
 | 
| -        return TypeError(node, output_type, rTagged);
 | 
| +        return TypeError(node, output_type, kRepTagged);
 | 
|        }
 | 
| -    } else if (output_type & rFloat64) {
 | 
| +    } else if (output_type & kRepFloat64) {
 | 
|        op = simplified()->ChangeFloat64ToTagged();
 | 
|      } else {
 | 
| -      return TypeError(node, output_type, rTagged);
 | 
| +      return TypeError(node, output_type, kRepTagged);
 | 
|      }
 | 
|      return jsgraph()->graph()->NewNode(op, node);
 | 
|    }
 | 
|  
 | 
| -  Node* GetFloat64RepresentationFor(Node* node, RepTypeUnion output_type) {
 | 
| +  Node* GetFloat64RepresentationFor(Node* node, MachineTypeUnion output_type) {
 | 
|      // Eagerly fold representation changes for constants.
 | 
|      switch (node->opcode()) {
 | 
|        case IrOpcode::kNumberConstant:
 | 
|          return jsgraph()->Float64Constant(ValueOf<double>(node->op()));
 | 
|        case IrOpcode::kInt32Constant:
 | 
| -        if (output_type & tUint32) {
 | 
| +        if (output_type & kTypeUint32) {
 | 
|            uint32_t value = ValueOf<uint32_t>(node->op());
 | 
|            return jsgraph()->Float64Constant(static_cast<double>(value));
 | 
|          } else {
 | 
| @@ -162,21 +129,23 @@ class RepresentationChanger {
 | 
|      }
 | 
|      // Select the correct X -> Float64 operator.
 | 
|      Operator* op;
 | 
| -    if (output_type & rWord32) {
 | 
| -      if (output_type & tUint32) {
 | 
| +    if (output_type & kRepBit) {
 | 
| +      return TypeError(node, output_type, kRepFloat64);
 | 
| +    } else if (output_type & rWord) {
 | 
| +      if (output_type & kTypeUint32) {
 | 
|          op = machine()->ChangeUint32ToFloat64();
 | 
|        } else {
 | 
|          op = machine()->ChangeInt32ToFloat64();
 | 
|        }
 | 
| -    } else if (output_type & rTagged) {
 | 
| +    } else if (output_type & kRepTagged) {
 | 
|        op = simplified()->ChangeTaggedToFloat64();
 | 
|      } else {
 | 
| -      return TypeError(node, output_type, rFloat64);
 | 
| +      return TypeError(node, output_type, kRepFloat64);
 | 
|      }
 | 
|      return jsgraph()->graph()->NewNode(op, node);
 | 
|    }
 | 
|  
 | 
| -  Node* GetWord32RepresentationFor(Node* node, RepTypeUnion output_type,
 | 
| +  Node* GetWord32RepresentationFor(Node* node, MachineTypeUnion output_type,
 | 
|                                     bool use_unsigned) {
 | 
|      // Eagerly fold representation changes for constants.
 | 
|      switch (node->opcode()) {
 | 
| @@ -200,27 +169,25 @@ class RepresentationChanger {
 | 
|      }
 | 
|      // Select the correct X -> Word32 operator.
 | 
|      Operator* op = NULL;
 | 
| -    if (output_type & rFloat64) {
 | 
| -      if (output_type & tUint32 || use_unsigned) {
 | 
| +    if (output_type & kRepFloat64) {
 | 
| +      if (output_type & kTypeUint32 || use_unsigned) {
 | 
|          op = machine()->ChangeFloat64ToUint32();
 | 
|        } else {
 | 
|          op = machine()->ChangeFloat64ToInt32();
 | 
|        }
 | 
| -    } else if (output_type & rTagged) {
 | 
| -      if (output_type & tUint32 || use_unsigned) {
 | 
| +    } else if (output_type & kRepTagged) {
 | 
| +      if (output_type & kTypeUint32 || use_unsigned) {
 | 
|          op = simplified()->ChangeTaggedToUint32();
 | 
|        } else {
 | 
|          op = simplified()->ChangeTaggedToInt32();
 | 
|        }
 | 
| -    } else if (output_type & rBit) {
 | 
| -      return node;  // Sloppy comparison -> word32.
 | 
|      } else {
 | 
| -      return TypeError(node, output_type, rWord32);
 | 
| +      return TypeError(node, output_type, kRepWord32);
 | 
|      }
 | 
|      return jsgraph()->graph()->NewNode(op, node);
 | 
|    }
 | 
|  
 | 
| -  Node* GetBitRepresentationFor(Node* node, RepTypeUnion output_type) {
 | 
| +  Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type) {
 | 
|      // Eagerly fold representation changes for constants.
 | 
|      switch (node->opcode()) {
 | 
|        case IrOpcode::kInt32Constant: {
 | 
| @@ -240,45 +207,24 @@ class RepresentationChanger {
 | 
|      }
 | 
|      // Select the correct X -> Bit operator.
 | 
|      Operator* op;
 | 
| -    if (output_type & rWord32) {
 | 
| +    if (output_type & rWord) {
 | 
|        return node;  // No change necessary.
 | 
| -    } else if (output_type & rWord64) {
 | 
| +    } else if (output_type & kRepWord64) {
 | 
|        return node;  // TODO(titzer): No change necessary, on 64-bit.
 | 
| -    } else if (output_type & rTagged) {
 | 
| +    } else if (output_type & kRepTagged) {
 | 
|        op = simplified()->ChangeBoolToBit();
 | 
|      } else {
 | 
| -      return TypeError(node, output_type, rBit);
 | 
| +      return TypeError(node, output_type, kRepBit);
 | 
|      }
 | 
|      return jsgraph()->graph()->NewNode(op, node);
 | 
|    }
 | 
|  
 | 
| -  Node* GetWord64RepresentationFor(Node* node, RepTypeUnion output_type) {
 | 
| -    if (output_type & rBit) {
 | 
| +  Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type) {
 | 
| +    if (output_type & kRepBit) {
 | 
|        return node;  // Sloppy comparison -> word64
 | 
|      }
 | 
|      // Can't really convert Word64 to anything else. Purported to be internal.
 | 
| -    return TypeError(node, output_type, rWord64);
 | 
| -  }
 | 
| -
 | 
| -  static RepType TypeForMachineType(MachineType rep) {
 | 
| -    // TODO(titzer): merge MachineType and RepType.
 | 
| -    switch (rep) {
 | 
| -      case kMachineWord8:
 | 
| -        return rWord32;
 | 
| -      case kMachineWord16:
 | 
| -        return rWord32;
 | 
| -      case kMachineWord32:
 | 
| -        return rWord32;
 | 
| -      case kMachineWord64:
 | 
| -        return rWord64;
 | 
| -      case kMachineFloat64:
 | 
| -        return rFloat64;
 | 
| -      case kMachineTagged:
 | 
| -        return rTagged;
 | 
| -      default:
 | 
| -        UNREACHABLE();
 | 
| -        return static_cast<RepType>(0);
 | 
| -    }
 | 
| +    return TypeError(node, output_type, kRepWord64);
 | 
|    }
 | 
|  
 | 
|    Operator* Int32OperatorFor(IrOpcode::Value opcode) {
 | 
| @@ -341,36 +287,22 @@ class RepresentationChanger {
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  RepType TypeForField(const FieldAccess& access) {
 | 
| -    RepType tElement = static_cast<RepType>(0);  // TODO(titzer)
 | 
| -    RepType rElement = TypeForMachineType(access.representation);
 | 
| -    return static_cast<RepType>(tElement | rElement);
 | 
| +  MachineType TypeForBasePointer(const FieldAccess& access) {
 | 
| +    return access.tag() != 0 ? kMachAnyTagged : kMachPtr;
 | 
|    }
 | 
|  
 | 
| -  RepType TypeForElement(const ElementAccess& access) {
 | 
| -    RepType tElement = static_cast<RepType>(0);  // TODO(titzer)
 | 
| -    RepType rElement = TypeForMachineType(access.representation);
 | 
| -    return static_cast<RepType>(tElement | rElement);
 | 
| +  MachineType TypeForBasePointer(const ElementAccess& access) {
 | 
| +    return access.tag() != 0 ? kMachAnyTagged : kMachPtr;
 | 
|    }
 | 
|  
 | 
| -  RepType TypeForBasePointer(const FieldAccess& access) {
 | 
| -    if (access.tag() != 0) return static_cast<RepType>(tAny | rTagged);
 | 
| -    return kPointerSize == 8 ? rWord64 : rWord32;
 | 
| -  }
 | 
| -
 | 
| -  RepType TypeForBasePointer(const ElementAccess& access) {
 | 
| -    if (access.tag() != 0) return static_cast<RepType>(tAny | rTagged);
 | 
| -    return kPointerSize == 8 ? rWord64 : rWord32;
 | 
| -  }
 | 
| -
 | 
| -  RepType TypeFromUpperBound(Type* type) {
 | 
| +  MachineType TypeFromUpperBound(Type* type) {
 | 
|      if (type->Is(Type::None()))
 | 
| -      return tAny;  // TODO(titzer): should be an error
 | 
| -    if (type->Is(Type::Signed32())) return tInt32;
 | 
| -    if (type->Is(Type::Unsigned32())) return tUint32;
 | 
| -    if (type->Is(Type::Number())) return tNumber;
 | 
| -    if (type->Is(Type::Boolean())) return tBool;
 | 
| -    return tAny;
 | 
| +      return kTypeAny;  // TODO(titzer): should be an error
 | 
| +    if (type->Is(Type::Signed32())) return kTypeInt32;
 | 
| +    if (type->Is(Type::Unsigned32())) return kTypeUint32;
 | 
| +    if (type->Is(Type::Number())) return kTypeNumber;
 | 
| +    if (type->Is(Type::Boolean())) return kTypeBool;
 | 
| +    return kTypeAny;
 | 
|    }
 | 
|  
 | 
|   private:
 | 
| @@ -384,17 +316,21 @@ class RepresentationChanger {
 | 
|    bool testing_type_errors_;  // If {true}, don't abort on a type error.
 | 
|    bool type_error_;           // Set when a type error is detected.
 | 
|  
 | 
| -  Node* TypeError(Node* node, RepTypeUnion output_type, RepTypeUnion use) {
 | 
| +  Node* TypeError(Node* node, MachineTypeUnion output_type,
 | 
| +                  MachineTypeUnion use) {
 | 
|      type_error_ = true;
 | 
|      if (!testing_type_errors_) {
 | 
| -      char buf1[REP_TYPE_STRLEN];
 | 
| -      char buf2[REP_TYPE_STRLEN];
 | 
| -      RenderRepTypeUnion(buf1, output_type);
 | 
| -      RenderRepTypeUnion(buf2, use);
 | 
| +      OStringStream out_str;
 | 
| +      out_str << static_cast<MachineType>(output_type);
 | 
| +
 | 
| +      OStringStream use_str;
 | 
| +      use_str << static_cast<MachineType>(use);
 | 
| +
 | 
|        V8_Fatal(__FILE__, __LINE__,
 | 
| -               "RepresentationChangerError: node #%d:%s of rep"
 | 
| -               "%s cannot be changed to rep%s",
 | 
| -               node->id(), node->op()->mnemonic(), buf1, buf2);
 | 
| +               "RepresentationChangerError: node #%d:%s of "
 | 
| +               "%s cannot be changed to %s",
 | 
| +               node->id(), node->op()->mnemonic(), out_str.c_str(),
 | 
| +               use_str.c_str());
 | 
|      }
 | 
|      return node;
 | 
|    }
 | 
| 
 |