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(); }
};