Upgrade V8 to version 4.9.385.28

https://chromium.googlesource.com/v8/v8/+/4.9.385.28

FPIIM-449

Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/compiler/representation-change.h b/src/compiler/representation-change.h
index 8720afd..62ea3b4 100644
--- a/src/compiler/representation-change.h
+++ b/src/compiler/representation-change.h
@@ -5,429 +5,106 @@
 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_
 #define V8_COMPILER_REPRESENTATION_CHANGE_H_
 
-#include <sstream>
-
-#include "src/base/bits.h"
 #include "src/compiler/js-graph.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/node-properties-inl.h"
 #include "src/compiler/simplified-operator.h"
 
 namespace v8 {
 namespace internal {
 namespace compiler {
 
+class Truncation final {
+ public:
+  // Constructors.
+  static Truncation None() { return Truncation(TruncationKind::kNone); }
+  static Truncation Bool() { return Truncation(TruncationKind::kBool); }
+  static Truncation Word32() { return Truncation(TruncationKind::kWord32); }
+  static Truncation Word64() { return Truncation(TruncationKind::kWord64); }
+  static Truncation Float32() { return Truncation(TruncationKind::kFloat32); }
+  static Truncation Float64() { return Truncation(TruncationKind::kFloat64); }
+  static Truncation Any() { return Truncation(TruncationKind::kAny); }
+
+  static Truncation Generalize(Truncation t1, Truncation t2) {
+    return Truncation(Generalize(t1.kind(), t2.kind()));
+  }
+
+  // Queries.
+  bool TruncatesToWord32() const {
+    return LessGeneral(kind_, TruncationKind::kWord32);
+  }
+  bool TruncatesNaNToZero() {
+    return LessGeneral(kind_, TruncationKind::kWord32) ||
+           LessGeneral(kind_, TruncationKind::kBool);
+  }
+  bool TruncatesUndefinedToZeroOrNaN() {
+    return LessGeneral(kind_, TruncationKind::kFloat64) ||
+           LessGeneral(kind_, TruncationKind::kWord64);
+  }
+
+  // Operators.
+  bool operator==(Truncation other) const { return kind() == other.kind(); }
+  bool operator!=(Truncation other) const { return !(*this == other); }
+
+  // Debug utilities.
+  const char* description() const;
+  bool IsLessGeneralThan(Truncation other) {
+    return LessGeneral(kind(), other.kind());
+  }
+
+ private:
+  enum class TruncationKind : uint8_t {
+    kNone,
+    kBool,
+    kWord32,
+    kWord64,
+    kFloat32,
+    kFloat64,
+    kAny
+  };
+
+  explicit Truncation(TruncationKind kind) : kind_(kind) {}
+  TruncationKind kind() const { return kind_; }
+
+  TruncationKind kind_;
+
+  static TruncationKind Generalize(TruncationKind rep1, TruncationKind rep2);
+  static bool LessGeneral(TruncationKind rep1, TruncationKind rep2);
+};
+
+
 // 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.
-class RepresentationChanger {
+class RepresentationChanger final {
  public:
-  RepresentationChanger(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified,
-                        Isolate* isolate)
+  RepresentationChanger(JSGraph* jsgraph, Isolate* isolate)
       : jsgraph_(jsgraph),
-        simplified_(simplified),
         isolate_(isolate),
         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, MachineTypeUnion output_type,
-                             MachineTypeUnion use_type) {
-    if (!base::bits::IsPowerOfTwo32(output_type & kRepMask)) {
-      // There should be only one output representation.
-      return TypeError(node, output_type, use_type);
-    }
-    if ((use_type & kRepMask) == (output_type & kRepMask)) {
-      // Representations are the same. That's a no-op.
-      return node;
-    }
-    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 & kRepFloat32) {
-      return GetFloat32RepresentationFor(node, output_type);
-    } else if (use_type & kRepFloat64) {
-      return GetFloat64RepresentationFor(node, output_type);
-    } else if (use_type & kRepBit) {
-      return GetBitRepresentationFor(node, output_type);
-    } 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, 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 & kTypeUint32) {
-          uint32_t value = OpParameter<uint32_t>(node);
-          return jsgraph()->Constant(static_cast<double>(value));
-        } else if (output_type & kTypeInt32) {
-          int32_t value = OpParameter<int32_t>(node);
-          return jsgraph()->Constant(value);
-        } else if (output_type & kRepBit) {
-          return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant()
-                                                 : jsgraph()->TrueConstant();
-        } else {
-          return TypeError(node, output_type, kRepTagged);
-        }
-      case IrOpcode::kFloat64Constant:
-        return jsgraph()->Constant(OpParameter<double>(node));
-      case IrOpcode::kFloat32Constant:
-        return jsgraph()->Constant(OpParameter<float>(node));
-      default:
-        break;
-    }
-    // Select the correct X -> Tagged operator.
-    const Operator* op;
-    if (output_type & kRepBit) {
-      op = simplified()->ChangeBitToBool();
-    } else if (output_type & rWord) {
-      if (output_type & kTypeUint32) {
-        op = simplified()->ChangeUint32ToTagged();
-      } else if (output_type & kTypeInt32) {
-        op = simplified()->ChangeInt32ToTagged();
-      } else {
-        return TypeError(node, output_type, kRepTagged);
-      }
-    } else if (output_type & kRepFloat32) {  // float32 -> float64 -> tagged
-      node = InsertChangeFloat32ToFloat64(node);
-      op = simplified()->ChangeFloat64ToTagged();
-    } else if (output_type & kRepFloat64) {
-      op = simplified()->ChangeFloat64ToTagged();
-    } else {
-      return TypeError(node, output_type, kRepTagged);
-    }
-    return jsgraph()->graph()->NewNode(op, node);
-  }
-
-  Node* GetFloat32RepresentationFor(Node* node, MachineTypeUnion output_type) {
-    // Eagerly fold representation changes for constants.
-    switch (node->opcode()) {
-      case IrOpcode::kFloat64Constant:
-      case IrOpcode::kNumberConstant:
-        return jsgraph()->Float32Constant(
-            DoubleToFloat32(OpParameter<double>(node)));
-      case IrOpcode::kInt32Constant:
-        if (output_type & kTypeUint32) {
-          uint32_t value = OpParameter<uint32_t>(node);
-          return jsgraph()->Float32Constant(static_cast<float>(value));
-        } else {
-          int32_t value = OpParameter<int32_t>(node);
-          return jsgraph()->Float32Constant(static_cast<float>(value));
-        }
-      case IrOpcode::kFloat32Constant:
-        return node;  // No change necessary.
-      default:
-        break;
-    }
-    // Select the correct X -> Float32 operator.
-    const Operator* op;
-    if (output_type & kRepBit) {
-      return TypeError(node, output_type, kRepFloat32);
-    } else if (output_type & rWord) {
-      if (output_type & kTypeUint32) {
-        op = machine()->ChangeUint32ToFloat64();
-      } else {
-        op = machine()->ChangeInt32ToFloat64();
-      }
-      // int32 -> float64 -> float32
-      node = jsgraph()->graph()->NewNode(op, node);
-      op = machine()->TruncateFloat64ToFloat32();
-    } else if (output_type & kRepTagged) {
-      op = simplified()
-               ->ChangeTaggedToFloat64();  // tagged -> float64 -> float32
-      node = jsgraph()->graph()->NewNode(op, node);
-      op = machine()->TruncateFloat64ToFloat32();
-    } else if (output_type & kRepFloat64) {
-      op = machine()->TruncateFloat64ToFloat32();
-    } else {
-      return TypeError(node, output_type, kRepFloat32);
-    }
-    return jsgraph()->graph()->NewNode(op, node);
-  }
-
-  Node* GetFloat64RepresentationFor(Node* node, MachineTypeUnion output_type) {
-    // Eagerly fold representation changes for constants.
-    switch (node->opcode()) {
-      case IrOpcode::kNumberConstant:
-        return jsgraph()->Float64Constant(OpParameter<double>(node));
-      case IrOpcode::kInt32Constant:
-        if (output_type & kTypeUint32) {
-          uint32_t value = OpParameter<uint32_t>(node);
-          return jsgraph()->Float64Constant(static_cast<double>(value));
-        } else {
-          int32_t value = OpParameter<int32_t>(node);
-          return jsgraph()->Float64Constant(value);
-        }
-      case IrOpcode::kFloat64Constant:
-        return node;  // No change necessary.
-      case IrOpcode::kFloat32Constant:
-        return jsgraph()->Float64Constant(OpParameter<float>(node));
-      default:
-        break;
-    }
-    // Select the correct X -> Float64 operator.
-    const Operator* op;
-    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 & kRepTagged) {
-      op = simplified()->ChangeTaggedToFloat64();
-    } else if (output_type & kRepFloat32) {
-      op = machine()->ChangeFloat32ToFloat64();
-    } else {
-      return TypeError(node, output_type, kRepFloat64);
-    }
-    return jsgraph()->graph()->NewNode(op, node);
-  }
-
-  Node* MakeInt32Constant(double value) {
-    if (value < 0) {
-      DCHECK(IsInt32Double(value));
-      int32_t iv = static_cast<int32_t>(value);
-      return jsgraph()->Int32Constant(iv);
-    } else {
-      DCHECK(IsUint32Double(value));
-      int32_t iv = static_cast<int32_t>(static_cast<uint32_t>(value));
-      return jsgraph()->Int32Constant(iv);
-    }
-  }
-
-  Node* GetTruncatedWord32For(Node* node, MachineTypeUnion output_type) {
-    // Eagerly fold truncations for constants.
-    switch (node->opcode()) {
-      case IrOpcode::kInt32Constant:
-        return node;  // No change necessary.
-      case IrOpcode::kFloat32Constant:
-        return jsgraph()->Int32Constant(
-            DoubleToInt32(OpParameter<float>(node)));
-      case IrOpcode::kNumberConstant:
-      case IrOpcode::kFloat64Constant:
-        return jsgraph()->Int32Constant(
-            DoubleToInt32(OpParameter<double>(node)));
-      default:
-        break;
-    }
-    // Select the correct X -> Word32 truncation operator.
-    const Operator* op = NULL;
-    if (output_type & kRepFloat64) {
-      op = machine()->TruncateFloat64ToInt32();
-    } else if (output_type & kRepFloat32) {
-      node = InsertChangeFloat32ToFloat64(node);
-      op = machine()->TruncateFloat64ToInt32();
-    } else if (output_type & kRepTagged) {
-      node = InsertChangeTaggedToFloat64(node);
-      op = machine()->TruncateFloat64ToInt32();
-    } else {
-      return TypeError(node, output_type, kRepWord32);
-    }
-    return jsgraph()->graph()->NewNode(op, node);
-  }
-
-  Node* GetWord32RepresentationFor(Node* node, MachineTypeUnion output_type,
-                                   bool use_unsigned) {
-    // Eagerly fold representation changes for constants.
-    switch (node->opcode()) {
-      case IrOpcode::kInt32Constant:
-        return node;  // No change necessary.
-      case IrOpcode::kFloat32Constant:
-        return MakeInt32Constant(OpParameter<float>(node));
-      case IrOpcode::kNumberConstant:
-      case IrOpcode::kFloat64Constant:
-        return MakeInt32Constant(OpParameter<double>(node));
-      default:
-        break;
-    }
-    // Select the correct X -> Word32 operator.
-    const Operator* op = NULL;
-    if (output_type & kRepFloat64) {
-      if (output_type & kTypeUint32 || use_unsigned) {
-        op = machine()->ChangeFloat64ToUint32();
-      } else {
-        op = machine()->ChangeFloat64ToInt32();
-      }
-    } else if (output_type & kRepFloat32) {
-      node = InsertChangeFloat32ToFloat64(node);  // float32 -> float64 -> int32
-      if (output_type & kTypeUint32 || use_unsigned) {
-        op = machine()->ChangeFloat64ToUint32();
-      } else {
-        op = machine()->ChangeFloat64ToInt32();
-      }
-    } else if (output_type & kRepTagged) {
-      if (output_type & kTypeUint32 || use_unsigned) {
-        op = simplified()->ChangeTaggedToUint32();
-      } else {
-        op = simplified()->ChangeTaggedToInt32();
-      }
-    } else {
-      return TypeError(node, output_type, kRepWord32);
-    }
-    return jsgraph()->graph()->NewNode(op, node);
-  }
-
-  Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type) {
-    // Eagerly fold representation changes for constants.
-    switch (node->opcode()) {
-      case IrOpcode::kInt32Constant: {
-        int32_t value = OpParameter<int32_t>(node);
-        if (value == 0 || value == 1) return node;
-        return jsgraph()->Int32Constant(1);  // value != 0
-      }
-      case IrOpcode::kNumberConstant: {
-        double value = OpParameter<double>(node);
-        if (std::isnan(value) || value == 0.0) {
-          return jsgraph()->Int32Constant(0);
-        }
-        return jsgraph()->Int32Constant(1);
-      }
-      case IrOpcode::kHeapConstant: {
-        Handle<Object> handle = OpParameter<Unique<Object> >(node).handle();
-        DCHECK(*handle == isolate()->heap()->true_value() ||
-               *handle == isolate()->heap()->false_value());
-        return jsgraph()->Int32Constant(
-            *handle == isolate()->heap()->true_value() ? 1 : 0);
-      }
-      default:
-        break;
-    }
-    // Select the correct X -> Bit operator.
-    const Operator* op;
-    if (output_type & rWord) {
-      return node;  // No change necessary.
-    } else if (output_type & kRepWord64) {
-      return node;  // TODO(titzer): No change necessary, on 64-bit.
-    } else if (output_type & kRepTagged) {
-      op = simplified()->ChangeBoolToBit();
-    } else {
-      return TypeError(node, output_type, kRepBit);
-    }
-    return jsgraph()->graph()->NewNode(op, node);
-  }
-
-  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, kRepWord64);
-  }
-
-  const Operator* Int32OperatorFor(IrOpcode::Value opcode) {
-    switch (opcode) {
-      case IrOpcode::kNumberAdd:
-        return machine()->Int32Add();
-      case IrOpcode::kNumberSubtract:
-        return machine()->Int32Sub();
-      case IrOpcode::kNumberMultiply:
-        return machine()->Int32Mul();
-      case IrOpcode::kNumberDivide:
-        return machine()->Int32Div();
-      case IrOpcode::kNumberModulus:
-        return machine()->Int32Mod();
-      case IrOpcode::kNumberEqual:
-        return machine()->Word32Equal();
-      case IrOpcode::kNumberLessThan:
-        return machine()->Int32LessThan();
-      case IrOpcode::kNumberLessThanOrEqual:
-        return machine()->Int32LessThanOrEqual();
-      default:
-        UNREACHABLE();
-        return NULL;
-    }
-  }
-
-  const Operator* Uint32OperatorFor(IrOpcode::Value opcode) {
-    switch (opcode) {
-      case IrOpcode::kNumberAdd:
-        return machine()->Int32Add();
-      case IrOpcode::kNumberSubtract:
-        return machine()->Int32Sub();
-      case IrOpcode::kNumberMultiply:
-        return machine()->Int32Mul();
-      case IrOpcode::kNumberDivide:
-        return machine()->Uint32Div();
-      case IrOpcode::kNumberModulus:
-        return machine()->Uint32Mod();
-      case IrOpcode::kNumberEqual:
-        return machine()->Word32Equal();
-      case IrOpcode::kNumberLessThan:
-        return machine()->Uint32LessThan();
-      case IrOpcode::kNumberLessThanOrEqual:
-        return machine()->Uint32LessThanOrEqual();
-      default:
-        UNREACHABLE();
-        return NULL;
-    }
-  }
-
-  const Operator* Float64OperatorFor(IrOpcode::Value opcode) {
-    switch (opcode) {
-      case IrOpcode::kNumberAdd:
-        return machine()->Float64Add();
-      case IrOpcode::kNumberSubtract:
-        return machine()->Float64Sub();
-      case IrOpcode::kNumberMultiply:
-        return machine()->Float64Mul();
-      case IrOpcode::kNumberDivide:
-        return machine()->Float64Div();
-      case IrOpcode::kNumberModulus:
-        return machine()->Float64Mod();
-      case IrOpcode::kNumberEqual:
-        return machine()->Float64Equal();
-      case IrOpcode::kNumberLessThan:
-        return machine()->Float64LessThan();
-      case IrOpcode::kNumberLessThanOrEqual:
-        return machine()->Float64LessThanOrEqual();
-      default:
-        UNREACHABLE();
-        return NULL;
-    }
-  }
+  // Changes representation from {output_type} to {use_rep}. The {truncation}
+  // parameter is only used for sanity checking - if the changer cannot figure
+  // out signedness for the word32->float64 conversion, then we check that the
+  // uses truncate to word32 (so they do not care about signedness).
+  Node* GetRepresentationFor(Node* node, MachineRepresentation output_rep,
+                             Type* output_type, MachineRepresentation use_rep,
+                             Truncation truncation = Truncation::None());
+  const Operator* Int32OperatorFor(IrOpcode::Value opcode);
+  const Operator* Uint32OperatorFor(IrOpcode::Value opcode);
+  const Operator* Float64OperatorFor(IrOpcode::Value opcode);
 
   MachineType TypeForBasePointer(const FieldAccess& access) {
-    return access.tag() != 0 ? kMachAnyTagged : kMachPtr;
+    return access.tag() != 0 ? MachineType::AnyTagged()
+                             : MachineType::Pointer();
   }
 
   MachineType TypeForBasePointer(const ElementAccess& access) {
-    return access.tag() != 0 ? kMachAnyTagged : kMachPtr;
-  }
-
-  MachineType TypeFromUpperBound(Type* type) {
-    if (type->Is(Type::None()))
-      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;
+    return access.tag() != 0 ? MachineType::AnyTagged()
+                             : MachineType::Pointer();
   }
 
  private:
   JSGraph* jsgraph_;
-  SimplifiedOperatorBuilder* simplified_;
   Isolate* isolate_;
 
   friend class RepresentationChangerTester;  // accesses the below fields.
@@ -435,38 +112,30 @@
   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, MachineTypeUnion output_type,
-                  MachineTypeUnion use) {
-    type_error_ = true;
-    if (!testing_type_errors_) {
-      std::ostringstream out_str;
-      out_str << static_cast<MachineType>(output_type);
+  Node* GetTaggedRepresentationFor(Node* node, MachineRepresentation output_rep,
+                                   Type* output_type);
+  Node* GetFloat32RepresentationFor(Node* node,
+                                    MachineRepresentation output_rep,
+                                    Type* output_type, Truncation truncation);
+  Node* GetFloat64RepresentationFor(Node* node,
+                                    MachineRepresentation output_rep,
+                                    Type* output_type, Truncation truncation);
+  Node* GetWord32RepresentationFor(Node* node, MachineRepresentation output_rep,
+                                   Type* output_type);
+  Node* GetBitRepresentationFor(Node* node, MachineRepresentation output_rep,
+                                Type* output_type);
+  Node* GetWord64RepresentationFor(Node* node, MachineRepresentation output_rep,
+                                   Type* output_type);
+  Node* TypeError(Node* node, MachineRepresentation output_rep,
+                  Type* output_type, MachineRepresentation use);
+  Node* MakeTruncatedInt32Constant(double value);
+  Node* InsertChangeFloat32ToFloat64(Node* node);
+  Node* InsertChangeTaggedToFloat64(Node* node);
 
-      std::ostringstream use_str;
-      use_str << static_cast<MachineType>(use);
-
-      V8_Fatal(__FILE__, __LINE__,
-               "RepresentationChangerError: node #%d:%s of "
-               "%s cannot be changed to %s",
-               node->id(), node->op()->mnemonic(), out_str.str().c_str(),
-               use_str.str().c_str());
-    }
-    return node;
-  }
-
-  Node* InsertChangeFloat32ToFloat64(Node* node) {
-    return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(),
-                                       node);
-  }
-
-  Node* InsertChangeTaggedToFloat64(Node* node) {
-    return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
-                                       node);
-  }
-
-  JSGraph* jsgraph() { return jsgraph_; }
-  Isolate* isolate() { return isolate_; }
-  SimplifiedOperatorBuilder* simplified() { return simplified_; }
+  JSGraph* jsgraph() const { return jsgraph_; }
+  Isolate* isolate() const { return isolate_; }
+  Factory* factory() const { return isolate()->factory(); }
+  SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
   MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
 };