Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 #include "src/compiler/representation-change.h" | 5 #include "src/compiler/representation-change.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 // Both are words less than or equal to 32-bits. | 135 // Both are words less than or equal to 32-bits. |
| 136 // Since loads of integers from memory implicitly sign or zero extend the | 136 // Since loads of integers from memory implicitly sign or zero extend the |
| 137 // value to the full machine word size and stores implicitly truncate, | 137 // value to the full machine word size and stores implicitly truncate, |
| 138 // no representation change is necessary. | 138 // no representation change is necessary. |
| 139 return node; | 139 return node; |
| 140 } | 140 } |
| 141 } | 141 } |
| 142 | 142 |
| 143 switch (use_info.representation()) { | 143 switch (use_info.representation()) { |
| 144 case MachineRepresentation::kTaggedSigned: | 144 case MachineRepresentation::kTaggedSigned: |
| 145 DCHECK(use_info.type_check() == TypeCheckKind::kNone); | 145 DCHECK(use_info.type_check() == TypeCheckKind::kNone || |
| 146 return GetTaggedSignedRepresentationFor(node, output_rep, output_type); | 146 use_info.type_check() == TypeCheckKind::kSignedSmall); |
| 147 return GetTaggedSignedRepresentationFor(node, output_rep, output_type, | |
| 148 use_node, use_info); | |
| 147 case MachineRepresentation::kTaggedPointer: | 149 case MachineRepresentation::kTaggedPointer: |
| 148 DCHECK(use_info.type_check() == TypeCheckKind::kNone); | 150 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 149 return GetTaggedPointerRepresentationFor(node, output_rep, output_type); | 151 return GetTaggedPointerRepresentationFor(node, output_rep, output_type); |
| 150 case MachineRepresentation::kTagged: | 152 case MachineRepresentation::kTagged: |
| 151 DCHECK(use_info.type_check() == TypeCheckKind::kNone); | 153 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 152 return GetTaggedRepresentationFor(node, output_rep, output_type, | 154 return GetTaggedRepresentationFor(node, output_rep, output_type, |
| 153 use_info.truncation()); | 155 use_info.truncation()); |
| 154 case MachineRepresentation::kFloat32: | 156 case MachineRepresentation::kFloat32: |
| 155 DCHECK(use_info.type_check() == TypeCheckKind::kNone); | 157 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 156 return GetFloat32RepresentationFor(node, output_rep, output_type, | 158 return GetFloat32RepresentationFor(node, output_rep, output_type, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 173 // TODO(bbudge) Handle conversions between tagged and untagged. | 175 // TODO(bbudge) Handle conversions between tagged and untagged. |
| 174 break; | 176 break; |
| 175 case MachineRepresentation::kNone: | 177 case MachineRepresentation::kNone: |
| 176 return node; | 178 return node; |
| 177 } | 179 } |
| 178 UNREACHABLE(); | 180 UNREACHABLE(); |
| 179 return nullptr; | 181 return nullptr; |
| 180 } | 182 } |
| 181 | 183 |
| 182 Node* RepresentationChanger::GetTaggedSignedRepresentationFor( | 184 Node* RepresentationChanger::GetTaggedSignedRepresentationFor( |
| 183 Node* node, MachineRepresentation output_rep, Type* output_type) { | 185 Node* node, MachineRepresentation output_rep, Type* output_type, |
| 186 Node* use_node, UseInfo use_info) { | |
| 184 // Eagerly fold representation changes for constants. | 187 // Eagerly fold representation changes for constants. |
| 185 switch (node->opcode()) { | 188 switch (node->opcode()) { |
| 186 case IrOpcode::kNumberConstant: { | 189 case IrOpcode::kNumberConstant: |
| 187 int32_t value = OpParameter<int32_t>(node); | 190 if (output_type->Is(Type::SignedSmall())) { |
|
Jarin
2016/09/23 08:31:54
Note: At some point we should compile away NumberC
Benedikt Meurer
2016/09/23 08:39:38
Acknowledged.
| |
| 188 if (Smi::IsValid(value)) { | 191 return node; |
| 189 return jsgraph()->Constant(value); | |
| 190 } | 192 } |
| 191 return TypeError(node, output_rep, output_type, | 193 break; |
| 192 MachineRepresentation::kTaggedSigned); | |
| 193 } | |
| 194 case IrOpcode::kHeapConstant: | |
| 195 return TypeError(node, output_rep, output_type, | |
| 196 MachineRepresentation::kTaggedSigned); | |
| 197 case IrOpcode::kInt32Constant: | |
| 198 if (output_type->Is(Type::SignedSmall())) { | |
| 199 int32_t value = OpParameter<int32_t>(node); | |
| 200 return jsgraph()->Constant(value); | |
| 201 } else { | |
| 202 return TypeError(node, output_rep, output_type, | |
| 203 MachineRepresentation::kTaggedSigned); | |
| 204 } | |
| 205 case IrOpcode::kFloat64Constant: | |
| 206 case IrOpcode::kFloat32Constant: | |
| 207 return TypeError(node, output_rep, output_type, | |
| 208 MachineRepresentation::kTaggedSigned); | |
| 209 default: | 194 default: |
| 210 break; | 195 break; |
| 211 } | 196 } |
| 212 // Select the correct X -> Tagged operator. | 197 // Select the correct X -> Tagged operator. |
| 213 const Operator* op; | 198 const Operator* op; |
| 214 if (Type::Semantic(output_type, jsgraph()->zone())->Is(Type::None())) { | 199 if (Type::Semantic(output_type, jsgraph()->zone())->Is(Type::None())) { |
| 215 // This is an impossible value; it should not be used at runtime. | 200 // This is an impossible value; it should not be used at runtime. |
| 216 // We just provide a dummy value here. | 201 // We just provide a dummy value here. |
| 217 return jsgraph()->Constant(0); | 202 return jsgraph()->Constant(0); |
| 218 } else if (IsWord(output_rep)) { | 203 } else if (IsWord(output_rep)) { |
| 219 if (output_type->Is(Type::Signed31())) { | 204 if (output_type->Is(Type::Signed31())) { |
| 220 op = simplified()->ChangeInt31ToTaggedSigned(); | 205 op = simplified()->ChangeInt31ToTaggedSigned(); |
| 221 } else if (machine()->Is64() && output_type->Is(Type::Signed32())) { | 206 } else if (output_type->Is(Type::Signed32())) { |
| 222 op = simplified()->ChangeInt32ToTagged(); | 207 if (SmiValuesAre32Bits()) { |
| 208 op = simplified()->ChangeInt32ToTagged(); | |
| 209 } else { | |
|
Jarin
2016/09/23 08:31:54
How about
else if (use_info.type_check() == Type
Benedikt Meurer
2016/09/23 08:39:38
Done.
| |
| 210 DCHECK_EQ(TypeCheckKind::kSignedSmall, use_info.type_check()); | |
| 211 op = simplified()->CheckedInt32ToTaggedSigned(); | |
| 212 } | |
| 213 } else if (output_type->Is(Type::Unsigned32())) { | |
| 214 DCHECK_EQ(TypeCheckKind::kSignedSmall, use_info.type_check()); | |
| 215 op = simplified()->CheckedUint32ToTaggedSigned(); | |
| 223 } else { | 216 } else { |
| 224 return TypeError(node, output_rep, output_type, | 217 return TypeError(node, output_rep, output_type, |
| 225 MachineRepresentation::kTaggedSigned); | 218 MachineRepresentation::kTaggedSigned); |
| 226 } | 219 } |
| 220 } else if (output_rep == MachineRepresentation::kFloat64) { | |
| 221 if (output_type->Is(Type::Signed31())) { | |
| 222 // float64 -> int32 -> tagged signed | |
| 223 node = InsertChangeFloat64ToInt32(node); | |
| 224 op = simplified()->ChangeInt31ToTaggedSigned(); | |
| 225 } else if (output_type->Is(Type::Signed32())) { | |
| 226 // float64 -> int32 -> tagged signed | |
| 227 node = InsertChangeFloat64ToInt32(node); | |
| 228 if (SmiValuesAre32Bits()) { | |
| 229 op = simplified()->ChangeInt32ToTagged(); | |
| 230 } else { | |
| 231 DCHECK_EQ(TypeCheckKind::kSignedSmall, use_info.type_check()); | |
| 232 op = simplified()->CheckedInt32ToTaggedSigned(); | |
| 233 } | |
| 234 } else if (output_type->Is(Type::Unsigned32())) { | |
| 235 // float64 -> uint32 -> tagged signed | |
| 236 DCHECK_EQ(TypeCheckKind::kSignedSmall, use_info.type_check()); | |
| 237 node = InsertChangeFloat64ToUint32(node); | |
| 238 op = simplified()->CheckedUint32ToTaggedSigned(); | |
| 239 } else { | |
| 240 DCHECK_EQ(TypeCheckKind::kSignedSmall, use_info.type_check()); | |
| 241 op = simplified()->CheckedFloat64ToInt32( | |
| 242 output_type->Maybe(Type::MinusZero()) | |
| 243 ? CheckForMinusZeroMode::kCheckForMinusZero | |
| 244 : CheckForMinusZeroMode::kDontCheckForMinusZero); | |
| 245 node = InsertConversion(node, op, use_node); | |
| 246 if (SmiValuesAre32Bits()) { | |
| 247 op = simplified()->ChangeInt32ToTagged(); | |
| 248 } else { | |
| 249 op = simplified()->CheckedInt32ToTaggedSigned(); | |
| 250 } | |
| 251 } | |
| 252 } else if (CanBeTaggedPointer(output_rep)) { | |
| 253 DCHECK_EQ(TypeCheckKind::kSignedSmall, use_info.type_check()); | |
| 254 op = simplified()->CheckedTaggedToTaggedSigned(); | |
| 255 } else if (output_rep == MachineRepresentation::kBit) { | |
| 256 // TODO(turbofan): Consider adding a Bailout operator that just deopts. | |
| 257 // Also use that for MachineRepresentation::kPointer case above. | |
| 258 DCHECK_EQ(TypeCheckKind::kSignedSmall, use_info.type_check()); | |
| 259 node = InsertChangeBitToTagged(node); | |
| 260 op = simplified()->CheckedTaggedToTaggedSigned(); | |
| 227 } else { | 261 } else { |
| 228 return TypeError(node, output_rep, output_type, | 262 return TypeError(node, output_rep, output_type, |
| 229 MachineRepresentation::kTaggedSigned); | 263 MachineRepresentation::kTaggedSigned); |
| 230 } | 264 } |
| 231 return jsgraph()->graph()->NewNode(op, node); | 265 return InsertConversion(node, op, use_node); |
| 232 } | 266 } |
| 233 | 267 |
| 234 Node* RepresentationChanger::GetTaggedPointerRepresentationFor( | 268 Node* RepresentationChanger::GetTaggedPointerRepresentationFor( |
| 235 Node* node, MachineRepresentation output_rep, Type* output_type) { | 269 Node* node, MachineRepresentation output_rep, Type* output_type) { |
| 236 // Eagerly fold representation changes for constants. | 270 // Eagerly fold representation changes for constants. |
| 237 switch (node->opcode()) { | 271 switch (node->opcode()) { |
| 238 case IrOpcode::kHeapConstant: | 272 case IrOpcode::kHeapConstant: |
| 239 return node; // No change necessary. | 273 return node; // No change necessary. |
| 240 case IrOpcode::kInt32Constant: | 274 case IrOpcode::kInt32Constant: |
| 241 if (output_type->Is(Type::Boolean())) { | 275 if (output_type->Is(Type::Boolean())) { |
| (...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 926 | 960 |
| 927 V8_Fatal(__FILE__, __LINE__, | 961 V8_Fatal(__FILE__, __LINE__, |
| 928 "RepresentationChangerError: node #%d:%s of " | 962 "RepresentationChangerError: node #%d:%s of " |
| 929 "%s cannot be changed to %s", | 963 "%s cannot be changed to %s", |
| 930 node->id(), node->op()->mnemonic(), out_str.str().c_str(), | 964 node->id(), node->op()->mnemonic(), out_str.str().c_str(), |
| 931 use_str.str().c_str()); | 965 use_str.str().c_str()); |
| 932 } | 966 } |
| 933 return node; | 967 return node; |
| 934 } | 968 } |
| 935 | 969 |
| 970 Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) { | |
| 971 return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node); | |
| 972 } | |
| 936 | 973 |
| 937 Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) { | 974 Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) { |
| 938 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node); | 975 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node); |
| 939 } | 976 } |
| 940 | 977 |
| 941 Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) { | 978 Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) { |
| 942 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node); | 979 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node); |
| 943 } | 980 } |
| 944 | 981 |
| 945 Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) { | 982 Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) { |
| 946 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node); | 983 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node); |
| 947 } | 984 } |
| 948 | 985 |
| 949 Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) { | 986 Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) { |
| 950 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), | 987 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), |
| 951 node); | 988 node); |
| 952 } | 989 } |
| 953 | 990 |
| 954 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { | 991 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { |
| 955 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), | 992 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), |
| 956 node); | 993 node); |
| 957 } | 994 } |
| 958 | 995 |
| 959 } // namespace compiler | 996 } // namespace compiler |
| 960 } // namespace internal | 997 } // namespace internal |
| 961 } // namespace v8 | 998 } // namespace v8 |
| OLD | NEW |