OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_ | 5 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_ |
6 #define V8_COMPILER_REPRESENTATION_CHANGE_H_ | 6 #define V8_COMPILER_REPRESENTATION_CHANGE_H_ |
7 | 7 |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
11 #include "src/compiler/js-graph.h" | 11 #include "src/compiler/js-graph.h" |
12 #include "src/compiler/machine-operator.h" | 12 #include "src/compiler/machine-operator.h" |
13 #include "src/compiler/node-properties-inl.h" | 13 #include "src/compiler/node-properties-inl.h" |
14 #include "src/compiler/simplified-operator.h" | 14 #include "src/compiler/simplified-operator.h" |
15 | 15 |
16 namespace v8 { | 16 namespace v8 { |
17 namespace internal { | 17 namespace internal { |
18 namespace compiler { | 18 namespace compiler { |
19 | 19 |
20 // Contains logic related to changing the representation of values for constants | 20 // Contains logic related to changing the representation of values for constants |
21 // and other nodes, as well as lowering Simplified->Machine operators. | 21 // and other nodes, as well as lowering Simplified->Machine operators. |
22 // Eagerly folds any representation changes for constants. | 22 // Eagerly folds any representation changes for constants. |
23 class RepresentationChanger { | 23 class RepresentationChanger { |
24 public: | 24 public: |
25 RepresentationChanger(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified, | 25 RepresentationChanger(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified, |
26 Isolate* isolate) | 26 Isolate* isolate) |
27 : jsgraph_(jsgraph), | 27 : jsgraph_(jsgraph), |
28 simplified_(simplified), | 28 simplified_(simplified), |
29 isolate_(isolate), | 29 isolate_(isolate), |
30 bit_range_(Type::Range(isolate->factory()->NewNumber(0), | |
31 isolate->factory()->NewNumber(1), | |
32 jsgraph->zone())), | |
33 testing_type_errors_(false), | 30 testing_type_errors_(false), |
34 type_error_(false) {} | 31 type_error_(false) {} |
35 | 32 |
36 // TODO(titzer): should Word64 also be implicitly convertable to others? | 33 // TODO(titzer): should Word64 also be implicitly convertable to others? |
37 static const MachineTypeUnion rWord = kRepWord8 | kRepWord16 | kRepWord32; | 34 static const MachineTypeUnion rWord = kRepWord8 | kRepWord16 | kRepWord32; |
38 | 35 |
39 Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type, | 36 Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type, |
40 MachineTypeUnion use_type) { | 37 MachineTypeUnion use_type) { |
41 if (!base::bits::IsPowerOfTwo32(output_type & kRepMask)) { | 38 if (!base::bits::IsPowerOfTwo32(output_type & kRepMask)) { |
42 // There should be only one output representation. | 39 // There should be only one output representation. |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 return MakeInt32Constant(OpParameter<float>(node)); | 256 return MakeInt32Constant(OpParameter<float>(node)); |
260 case IrOpcode::kNumberConstant: | 257 case IrOpcode::kNumberConstant: |
261 case IrOpcode::kFloat64Constant: | 258 case IrOpcode::kFloat64Constant: |
262 return MakeInt32Constant(OpParameter<double>(node)); | 259 return MakeInt32Constant(OpParameter<double>(node)); |
263 default: | 260 default: |
264 break; | 261 break; |
265 } | 262 } |
266 // Select the correct X -> Word32 operator. | 263 // Select the correct X -> Word32 operator. |
267 const Operator* op; | 264 const Operator* op; |
268 if (output_type & kRepBit) { | 265 if (output_type & kRepBit) { |
269 return node; // No change necessary. | 266 return node; // Sloppy comparison -> word32 |
270 } else if (output_type & kRepFloat64) { | 267 } else if (output_type & kRepFloat64) { |
271 if (output_type & kTypeUint32 || use_unsigned) { | 268 if (output_type & kTypeUint32 || use_unsigned) { |
272 op = machine()->ChangeFloat64ToUint32(); | 269 op = machine()->ChangeFloat64ToUint32(); |
273 } else { | 270 } else { |
274 op = machine()->ChangeFloat64ToInt32(); | 271 op = machine()->ChangeFloat64ToInt32(); |
275 } | 272 } |
276 } else if (output_type & kRepFloat32) { | 273 } else if (output_type & kRepFloat32) { |
277 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 | 274 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 |
278 if (output_type & kTypeUint32 || use_unsigned) { | 275 if (output_type & kTypeUint32 || use_unsigned) { |
279 op = machine()->ChangeFloat64ToUint32(); | 276 op = machine()->ChangeFloat64ToUint32(); |
280 } else { | 277 } else { |
281 op = machine()->ChangeFloat64ToInt32(); | 278 op = machine()->ChangeFloat64ToInt32(); |
282 } | 279 } |
283 } else if (output_type & kRepTagged) { | 280 } else if (output_type & kRepTagged) { |
284 if (output_type & kTypeUint32 || use_unsigned) { | 281 if (output_type & kTypeUint32 || use_unsigned) { |
285 op = simplified()->ChangeTaggedToUint32(); | 282 op = simplified()->ChangeTaggedToUint32(); |
286 } else { | 283 } else { |
287 op = simplified()->ChangeTaggedToInt32(); | 284 op = simplified()->ChangeTaggedToInt32(); |
288 } | 285 } |
289 } else { | 286 } else { |
290 return TypeError(node, output_type, kRepWord32); | 287 return TypeError(node, output_type, kRepWord32); |
291 } | 288 } |
292 return jsgraph()->graph()->NewNode(op, node); | 289 return jsgraph()->graph()->NewNode(op, node); |
293 } | 290 } |
294 | 291 |
295 Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type) { | 292 Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type) { |
296 // Eagerly fold representation changes for constants. | 293 // Eagerly fold representation changes for constants. |
297 switch (node->opcode()) { | 294 switch (node->opcode()) { |
298 case IrOpcode::kInt32Constant: { | |
299 int32_t value = OpParameter<int32_t>(node); | |
300 if (value == 0 || value == 1) return node; | |
301 return jsgraph()->Int32Constant(1); // value != 0 | |
302 } | |
303 case IrOpcode::kNumberConstant: { | |
304 double value = OpParameter<double>(node); | |
305 if (value == 0 || std::isnan(value)) return jsgraph()->Int32Constant(0); | |
306 return jsgraph()->Int32Constant(1); // value != +0.0, -0.0, NaN | |
307 } | |
308 case IrOpcode::kHeapConstant: { | 295 case IrOpcode::kHeapConstant: { |
309 Handle<Object> object = OpParameter<Unique<Object>>(node).handle(); | 296 Handle<Object> value = OpParameter<Unique<Object> >(node).handle(); |
310 return jsgraph()->Int32Constant(object->BooleanValue() ? 1 : 0); | 297 DCHECK(value.is_identical_to(factory()->true_value()) || |
| 298 value.is_identical_to(factory()->false_value())); |
| 299 return jsgraph()->Int32Constant( |
| 300 value.is_identical_to(factory()->true_value()) ? 1 : 0); |
311 } | 301 } |
312 default: | 302 default: |
313 break; | 303 break; |
314 } | 304 } |
315 // Select the correct X -> Bit operator. | 305 // Select the correct X -> Bit operator. |
316 const Operator* op; | 306 const Operator* op; |
317 if (output_type & rWord) { | 307 if (output_type & kRepTagged) { |
318 op = simplified()->ChangeWord32ToBit(); | 308 op = simplified()->ChangeBoolToBit(); |
319 } else if (output_type & kRepWord64) { | |
320 op = simplified()->ChangeWord64ToBit(); | |
321 } else if (output_type & kRepTagged) { | |
322 Type* upper = NodeProperties::GetBounds(node).upper; | |
323 if (upper->Is(Type::Boolean())) { | |
324 op = simplified()->ChangeBoolToBit(); | |
325 } else if (upper->Is(Type::Signed32())) { | |
326 // Tagged -> Int32 -> Bit | |
327 node = InsertChangeTaggedToInt32(node); | |
328 op = simplified()->ChangeWord32ToBit(); | |
329 } else if (upper->Is(Type::Unsigned32())) { | |
330 // Tagged -> Uint32 -> Bit | |
331 node = InsertChangeTaggedToUint32(node); | |
332 op = simplified()->ChangeWord32ToBit(); | |
333 } else { | |
334 return TypeError(node, output_type, kRepBit); | |
335 } | |
336 } else { | 309 } else { |
337 return TypeError(node, output_type, kRepBit); | 310 return TypeError(node, output_type, kRepBit); |
338 } | 311 } |
339 return graph()->NewNode(op, node); | 312 return jsgraph()->graph()->NewNode(op, node); |
340 } | 313 } |
341 | 314 |
342 Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type) { | 315 Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type) { |
343 if (output_type & kRepBit) { | 316 if (output_type & kRepBit) { |
344 return node; // Sloppy comparison -> word64 | 317 return node; // Sloppy comparison -> word64 |
345 } | 318 } |
346 // Can't really convert Word64 to anything else. Purported to be internal. | 319 // Can't really convert Word64 to anything else. Purported to be internal. |
347 return TypeError(node, output_type, kRepWord64); | 320 return TypeError(node, output_type, kRepWord64); |
348 } | 321 } |
349 | 322 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 if (type->Is(Type::Unsigned32())) return kTypeUint32; | 407 if (type->Is(Type::Unsigned32())) return kTypeUint32; |
435 if (type->Is(Type::Number())) return kTypeNumber; | 408 if (type->Is(Type::Number())) return kTypeNumber; |
436 if (type->Is(Type::Boolean())) return kTypeBool; | 409 if (type->Is(Type::Boolean())) return kTypeBool; |
437 return kTypeAny; | 410 return kTypeAny; |
438 } | 411 } |
439 | 412 |
440 private: | 413 private: |
441 JSGraph* jsgraph_; | 414 JSGraph* jsgraph_; |
442 SimplifiedOperatorBuilder* simplified_; | 415 SimplifiedOperatorBuilder* simplified_; |
443 Isolate* isolate_; | 416 Isolate* isolate_; |
444 Type* bit_range_; | |
445 | 417 |
446 friend class RepresentationChangerTester; // accesses the below fields. | 418 friend class RepresentationChangerTester; // accesses the below fields. |
447 | 419 |
448 bool testing_type_errors_; // If {true}, don't abort on a type error. | 420 bool testing_type_errors_; // If {true}, don't abort on a type error. |
449 bool type_error_; // Set when a type error is detected. | 421 bool type_error_; // Set when a type error is detected. |
450 | 422 |
451 Node* TypeError(Node* node, MachineTypeUnion output_type, | 423 Node* TypeError(Node* node, MachineTypeUnion output_type, |
452 MachineTypeUnion use) { | 424 MachineTypeUnion use) { |
453 type_error_ = true; | 425 type_error_ = true; |
454 if (!testing_type_errors_) { | 426 if (!testing_type_errors_) { |
455 std::ostringstream out_str; | 427 std::ostringstream out_str; |
456 out_str << static_cast<MachineType>(output_type); | 428 out_str << static_cast<MachineType>(output_type); |
457 | 429 |
458 std::ostringstream use_str; | 430 std::ostringstream use_str; |
459 use_str << static_cast<MachineType>(use); | 431 use_str << static_cast<MachineType>(use); |
460 | 432 |
461 V8_Fatal(__FILE__, __LINE__, | 433 V8_Fatal(__FILE__, __LINE__, |
462 "RepresentationChangerError: node #%d:%s of " | 434 "RepresentationChangerError: node #%d:%s of " |
463 "%s cannot be changed to %s", | 435 "%s cannot be changed to %s", |
464 node->id(), node->op()->mnemonic(), out_str.str().c_str(), | 436 node->id(), node->op()->mnemonic(), out_str.str().c_str(), |
465 use_str.str().c_str()); | 437 use_str.str().c_str()); |
466 } | 438 } |
467 return node; | 439 return node; |
468 } | 440 } |
469 | 441 |
470 Node* InsertChangeFloat32ToFloat64(Node* node) { | 442 Node* InsertChangeFloat32ToFloat64(Node* node) { |
471 return graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node); | 443 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), |
| 444 node); |
472 } | 445 } |
473 | 446 |
474 Node* InsertChangeTaggedToFloat64(Node* node) { | 447 Node* InsertChangeTaggedToFloat64(Node* node) { |
475 return graph()->NewNode(simplified()->ChangeTaggedToFloat64(), node); | 448 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), |
| 449 node); |
476 } | 450 } |
477 | 451 |
478 Node* InsertChangeTaggedToInt32(Node* node) { | |
479 return graph()->NewNode(simplified()->ChangeTaggedToInt32(), node); | |
480 } | |
481 | |
482 Node* InsertChangeTaggedToUint32(Node* node) { | |
483 return graph()->NewNode(simplified()->ChangeTaggedToUint32(), node); | |
484 } | |
485 | |
486 Graph* graph() const { return jsgraph()->graph(); } | |
487 JSGraph* jsgraph() const { return jsgraph_; } | 452 JSGraph* jsgraph() const { return jsgraph_; } |
488 Isolate* isolate() const { return isolate_; } | 453 Isolate* isolate() const { return isolate_; } |
489 SimplifiedOperatorBuilder* simplified() const { return simplified_; } | 454 Factory* factory() const { return isolate()->factory(); } |
490 MachineOperatorBuilder* machine() const { return jsgraph()->machine(); } | 455 SimplifiedOperatorBuilder* simplified() { return simplified_; } |
| 456 MachineOperatorBuilder* machine() { return jsgraph()->machine(); } |
491 }; | 457 }; |
492 | 458 |
493 } // namespace compiler | 459 } // namespace compiler |
494 } // namespace internal | 460 } // namespace internal |
495 } // namespace v8 | 461 } // namespace v8 |
496 | 462 |
497 #endif // V8_COMPILER_REPRESENTATION_CHANGE_H_ | 463 #endif // V8_COMPILER_REPRESENTATION_CHANGE_H_ |
OLD | NEW |