Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: src/compiler/representation-change.h

Issue 850013003: [turbofan] Fix truncation/representation sloppiness wrt. bool/bit. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fixes/Cleanups Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/opcodes.h ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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_
OLDNEW
« no previous file with comments | « src/compiler/opcodes.h ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698