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; |
} |