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())) { |
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 if (use_info.type_check() == TypeCheckKind::kSignedSmall) { |
| 210 op = simplified()->CheckedInt32ToTaggedSigned(); |
| 211 } else { |
| 212 return TypeError(node, output_rep, output_type, |
| 213 MachineRepresentation::kTaggedSigned); |
| 214 } |
| 215 } else if (output_type->Is(Type::Unsigned32()) && |
| 216 use_info.type_check() == TypeCheckKind::kSignedSmall) { |
| 217 op = simplified()->CheckedUint32ToTaggedSigned(); |
223 } else { | 218 } else { |
224 return TypeError(node, output_rep, output_type, | 219 return TypeError(node, output_rep, output_type, |
225 MachineRepresentation::kTaggedSigned); | 220 MachineRepresentation::kTaggedSigned); |
226 } | 221 } |
| 222 } else if (output_rep == MachineRepresentation::kFloat64) { |
| 223 if (output_type->Is(Type::Signed31())) { |
| 224 // float64 -> int32 -> tagged signed |
| 225 node = InsertChangeFloat64ToInt32(node); |
| 226 op = simplified()->ChangeInt31ToTaggedSigned(); |
| 227 } else if (output_type->Is(Type::Signed32())) { |
| 228 // float64 -> int32 -> tagged signed |
| 229 node = InsertChangeFloat64ToInt32(node); |
| 230 if (SmiValuesAre32Bits()) { |
| 231 op = simplified()->ChangeInt32ToTagged(); |
| 232 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { |
| 233 op = simplified()->CheckedInt32ToTaggedSigned(); |
| 234 } else { |
| 235 return TypeError(node, output_rep, output_type, |
| 236 MachineRepresentation::kTaggedSigned); |
| 237 } |
| 238 } else if (output_type->Is(Type::Unsigned32()) && |
| 239 use_info.type_check() == TypeCheckKind::kSignedSmall) { |
| 240 // float64 -> uint32 -> tagged signed |
| 241 node = InsertChangeFloat64ToUint32(node); |
| 242 op = simplified()->CheckedUint32ToTaggedSigned(); |
| 243 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { |
| 244 op = simplified()->CheckedFloat64ToInt32( |
| 245 output_type->Maybe(Type::MinusZero()) |
| 246 ? CheckForMinusZeroMode::kCheckForMinusZero |
| 247 : CheckForMinusZeroMode::kDontCheckForMinusZero); |
| 248 node = InsertConversion(node, op, use_node); |
| 249 if (SmiValuesAre32Bits()) { |
| 250 op = simplified()->ChangeInt32ToTagged(); |
| 251 } else { |
| 252 op = simplified()->CheckedInt32ToTaggedSigned(); |
| 253 } |
| 254 } else { |
| 255 return TypeError(node, output_rep, output_type, |
| 256 MachineRepresentation::kTaggedSigned); |
| 257 } |
| 258 } else if (CanBeTaggedPointer(output_rep) && |
| 259 use_info.type_check() == TypeCheckKind::kSignedSmall) { |
| 260 op = simplified()->CheckedTaggedToTaggedSigned(); |
| 261 } else if (output_rep == MachineRepresentation::kBit && |
| 262 use_info.type_check() == TypeCheckKind::kSignedSmall) { |
| 263 // TODO(turbofan): Consider adding a Bailout operator that just deopts. |
| 264 // Also use that for MachineRepresentation::kPointer case above. |
| 265 node = InsertChangeBitToTagged(node); |
| 266 op = simplified()->CheckedTaggedToTaggedSigned(); |
227 } else { | 267 } else { |
228 return TypeError(node, output_rep, output_type, | 268 return TypeError(node, output_rep, output_type, |
229 MachineRepresentation::kTaggedSigned); | 269 MachineRepresentation::kTaggedSigned); |
230 } | 270 } |
231 return jsgraph()->graph()->NewNode(op, node); | 271 return InsertConversion(node, op, use_node); |
232 } | 272 } |
233 | 273 |
234 Node* RepresentationChanger::GetTaggedPointerRepresentationFor( | 274 Node* RepresentationChanger::GetTaggedPointerRepresentationFor( |
235 Node* node, MachineRepresentation output_rep, Type* output_type) { | 275 Node* node, MachineRepresentation output_rep, Type* output_type) { |
236 // Eagerly fold representation changes for constants. | 276 // Eagerly fold representation changes for constants. |
237 switch (node->opcode()) { | 277 switch (node->opcode()) { |
238 case IrOpcode::kHeapConstant: | 278 case IrOpcode::kHeapConstant: |
239 return node; // No change necessary. | 279 return node; // No change necessary. |
240 case IrOpcode::kInt32Constant: | 280 case IrOpcode::kInt32Constant: |
241 if (output_type->Is(Type::Boolean())) { | 281 if (output_type->Is(Type::Boolean())) { |
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 | 966 |
927 V8_Fatal(__FILE__, __LINE__, | 967 V8_Fatal(__FILE__, __LINE__, |
928 "RepresentationChangerError: node #%d:%s of " | 968 "RepresentationChangerError: node #%d:%s of " |
929 "%s cannot be changed to %s", | 969 "%s cannot be changed to %s", |
930 node->id(), node->op()->mnemonic(), out_str.str().c_str(), | 970 node->id(), node->op()->mnemonic(), out_str.str().c_str(), |
931 use_str.str().c_str()); | 971 use_str.str().c_str()); |
932 } | 972 } |
933 return node; | 973 return node; |
934 } | 974 } |
935 | 975 |
| 976 Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) { |
| 977 return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node); |
| 978 } |
936 | 979 |
937 Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) { | 980 Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) { |
938 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node); | 981 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node); |
939 } | 982 } |
940 | 983 |
941 Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) { | 984 Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) { |
942 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node); | 985 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node); |
943 } | 986 } |
944 | 987 |
945 Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) { | 988 Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) { |
946 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node); | 989 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node); |
947 } | 990 } |
948 | 991 |
949 Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) { | 992 Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) { |
950 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), | 993 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), |
951 node); | 994 node); |
952 } | 995 } |
953 | 996 |
954 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { | 997 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { |
955 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), | 998 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), |
956 node); | 999 node); |
957 } | 1000 } |
958 | 1001 |
959 } // namespace compiler | 1002 } // namespace compiler |
960 } // namespace internal | 1003 } // namespace internal |
961 } // namespace v8 | 1004 } // namespace v8 |
OLD | NEW |