| Index: src/compiler/representation-change.h
|
| diff --git a/src/compiler/representation-change.h b/src/compiler/representation-change.h
|
| index bd5fb5f79349b7abf95233f7bcf7d0111b98267a..8b898767358cb3ef8027ffb1693fc9403ea9cf02 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;
|
| + PrintMachineTypeUnionTo(out_str, output_type);
|
| +
|
| + OStringStream use_str;
|
| + PrintMachineTypeUnionTo(use_str, 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;
|
| }
|
|
|