Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/compiler/representation-change.cc b/src/compiler/representation-change.cc
index 180355d..d1aa5af 100644
--- a/src/compiler/representation-change.cc
+++ b/src/compiler/representation-change.cc
@@ -105,46 +105,55 @@
} // namespace
-
// Changes representation from {output_rep} 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* RepresentationChanger::GetRepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type,
- MachineRepresentation use_rep, Truncation truncation) {
+ Node* use_node, UseInfo use_info) {
if (output_rep == MachineRepresentation::kNone) {
// The output representation should be set.
- return TypeError(node, output_rep, output_type, use_rep);
+ return TypeError(node, output_rep, output_type, use_info.representation());
}
- if (use_rep == output_rep) {
- // Representations are the same. That's a no-op.
- return node;
+
+ // Handle the no-op shortcuts when no checking is necessary.
+ if (use_info.type_check() == TypeCheckKind::kNone ||
+ output_rep != MachineRepresentation::kWord32) {
+ if (use_info.representation() == output_rep) {
+ // Representations are the same. That's a no-op.
+ return node;
+ }
+ if (IsWord(use_info.representation()) && IsWord(output_rep)) {
+ // 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 (IsWord(use_rep) && IsWord(output_rep)) {
- // 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;
- }
- switch (use_rep) {
+
+ switch (use_info.representation()) {
case MachineRepresentation::kTagged:
+ DCHECK(use_info.type_check() == TypeCheckKind::kNone);
return GetTaggedRepresentationFor(node, output_rep, output_type);
case MachineRepresentation::kFloat32:
+ DCHECK(use_info.type_check() == TypeCheckKind::kNone);
return GetFloat32RepresentationFor(node, output_rep, output_type,
- truncation);
+ use_info.truncation());
case MachineRepresentation::kFloat64:
return GetFloat64RepresentationFor(node, output_rep, output_type,
- truncation);
+ use_node, use_info);
case MachineRepresentation::kBit:
+ DCHECK(use_info.type_check() == TypeCheckKind::kNone);
return GetBitRepresentationFor(node, output_rep, output_type);
case MachineRepresentation::kWord8:
case MachineRepresentation::kWord16:
case MachineRepresentation::kWord32:
- return GetWord32RepresentationFor(node, output_rep, output_type,
- truncation);
+ return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
+ use_info);
case MachineRepresentation::kWord64:
+ DCHECK(use_info.type_check() == TypeCheckKind::kNone);
return GetWord64RepresentationFor(node, output_rep, output_type);
case MachineRepresentation::kSimd128: // Fall through.
// TODO(bbudge) Handle conversions between tagged and untagged.
@@ -156,7 +165,6 @@
return nullptr;
}
-
Node* RepresentationChanger::GetTaggedRepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type) {
// Eagerly fold representation changes for constants.
@@ -271,8 +279,12 @@
}
} else if (output_rep == MachineRepresentation::kTagged) {
if (output_type->Is(Type::NumberOrUndefined())) {
- op = simplified()
- ->ChangeTaggedToFloat64(); // tagged -> float64 -> float32
+ // tagged -> float64 -> float32
+ if (output_type->Is(Type::Number())) {
+ op = simplified()->ChangeTaggedToFloat64();
+ } else {
+ op = simplified()->TruncateTaggedToFloat64();
+ }
node = jsgraph()->graph()->NewNode(op, node);
op = machine()->TruncateFloat64ToFloat32();
}
@@ -286,29 +298,31 @@
return jsgraph()->graph()->NewNode(op, node);
}
-
Node* RepresentationChanger::GetFloat64RepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type,
- Truncation truncation) {
+ Node* use_node, UseInfo use_info) {
// Eagerly fold representation changes for constants.
- switch (node->opcode()) {
- case IrOpcode::kNumberConstant:
- return jsgraph()->Float64Constant(OpParameter<double>(node));
- case IrOpcode::kInt32Constant:
- if (output_type->Is(Type::Signed32())) {
- int32_t value = OpParameter<int32_t>(node);
- return jsgraph()->Float64Constant(value);
- } else {
- DCHECK(output_type->Is(Type::Unsigned32()));
- uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
- return jsgraph()->Float64Constant(static_cast<double>(value));
- }
- case IrOpcode::kFloat64Constant:
- return node; // No change necessary.
- case IrOpcode::kFloat32Constant:
- return jsgraph()->Float64Constant(OpParameter<float>(node));
- default:
- break;
+ if ((use_info.type_check() == TypeCheckKind::kNone)) {
+ // TODO(jarin) Handle checked constant conversions.
+ switch (node->opcode()) {
+ case IrOpcode::kNumberConstant:
+ return jsgraph()->Float64Constant(OpParameter<double>(node));
+ case IrOpcode::kInt32Constant:
+ if (output_type->Is(Type::Signed32())) {
+ int32_t value = OpParameter<int32_t>(node);
+ return jsgraph()->Float64Constant(value);
+ } else {
+ DCHECK(output_type->Is(Type::Unsigned32()));
+ uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
+ return jsgraph()->Float64Constant(static_cast<double>(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 = nullptr;
@@ -316,7 +330,7 @@
if (output_type->Is(Type::Signed32())) {
op = machine()->ChangeInt32ToFloat64();
} else if (output_type->Is(Type::Unsigned32()) ||
- truncation.TruncatesToWord32()) {
+ use_info.truncation().TruncatesToWord32()) {
// Either the output is uint32 or the uses only care about the
// low 32 bits (so we can pick uint32 safely).
op = machine()->ChangeUint32ToFloat64();
@@ -328,8 +342,13 @@
} else if (output_type->Is(Type::TaggedSigned())) {
node = InsertChangeTaggedSignedToInt32(node);
op = machine()->ChangeInt32ToFloat64();
- } else if (output_type->Is(Type::NumberOrUndefined())) {
+ } else if (output_type->Is(Type::Number())) {
op = simplified()->ChangeTaggedToFloat64();
+ } else if (output_type->Is(Type::NumberOrUndefined())) {
+ // TODO(jarin) Here we should check that truncation is Number.
+ op = simplified()->TruncateTaggedToFloat64();
+ } else if (use_info.type_check() == TypeCheckKind::kNumberOrUndefined) {
+ op = simplified()->CheckedTaggedToFloat64();
}
} else if (output_rep == MachineRepresentation::kFloat32) {
op = machine()->ChangeFloat32ToFloat64();
@@ -338,29 +357,43 @@
return TypeError(node, output_rep, output_type,
MachineRepresentation::kFloat64);
}
- return jsgraph()->graph()->NewNode(op, node);
+ return InsertConversion(node, op, use_node);
}
-
Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
return jsgraph()->Int32Constant(DoubleToInt32(value));
}
Node* RepresentationChanger::GetWord32RepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type,
- Truncation truncation) {
+ Node* use_node, UseInfo use_info) {
// Eagerly fold representation changes for constants.
switch (node->opcode()) {
case IrOpcode::kInt32Constant:
return node; // No change necessary.
- case IrOpcode::kFloat32Constant:
- return MakeTruncatedInt32Constant(OpParameter<float>(node));
+ case IrOpcode::kFloat32Constant: {
+ float const fv = OpParameter<float>(node);
+ if (use_info.type_check() == TypeCheckKind::kNone ||
+ (use_info.type_check() == TypeCheckKind::kSigned32 &&
+ IsInt32Double(fv))) {
+ return MakeTruncatedInt32Constant(fv);
+ }
+ break;
+ }
case IrOpcode::kNumberConstant:
- case IrOpcode::kFloat64Constant:
- return MakeTruncatedInt32Constant(OpParameter<double>(node));
+ case IrOpcode::kFloat64Constant: {
+ double const fv = OpParameter<double>(node);
+ if (use_info.type_check() == TypeCheckKind::kNone ||
+ (use_info.type_check() == TypeCheckKind::kSigned32 &&
+ IsInt32Double(fv))) {
+ return MakeTruncatedInt32Constant(fv);
+ }
+ break;
+ }
default:
break;
}
+
// Select the correct X -> Word32 operator.
const Operator* op = nullptr;
if (output_rep == MachineRepresentation::kBit) {
@@ -370,8 +403,10 @@
op = machine()->ChangeFloat64ToUint32();
} else if (output_type->Is(Type::Signed32())) {
op = machine()->ChangeFloat64ToInt32();
- } else if (truncation.TruncatesToWord32()) {
+ } else if (use_info.truncation().TruncatesToWord32()) {
op = machine()->TruncateFloat64ToWord32();
+ } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
+ op = simplified()->CheckedFloat64ToInt32();
}
} else if (output_rep == MachineRepresentation::kFloat32) {
node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
@@ -379,8 +414,10 @@
op = machine()->ChangeFloat64ToUint32();
} else if (output_type->Is(Type::Signed32())) {
op = machine()->ChangeFloat64ToInt32();
- } else if (truncation.TruncatesToWord32()) {
+ } else if (use_info.truncation().TruncatesToWord32()) {
op = machine()->TruncateFloat64ToWord32();
+ } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
+ op = simplified()->CheckedFloat64ToInt32();
}
} else if (output_rep == MachineRepresentation::kTagged) {
if (output_type->Is(Type::TaggedSigned())) {
@@ -389,14 +426,45 @@
op = simplified()->ChangeTaggedToUint32();
} else if (output_type->Is(Type::Signed32())) {
op = simplified()->ChangeTaggedToInt32();
- } else if (truncation.TruncatesToWord32()) {
+ } else if (use_info.truncation().TruncatesToWord32()) {
op = simplified()->TruncateTaggedToWord32();
+ } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
+ op = simplified()->CheckedTaggedToInt32();
}
+ } else if (output_rep == MachineRepresentation::kWord32) {
+ // Only the checked case should get here, the non-checked case is
+ // handled in GetRepresentationFor.
+ DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
+ if (output_type->Is(Type::Signed32())) {
+ return node;
+ } else if (output_type->Is(Type::Unsigned32())) {
+ op = simplified()->CheckedUint32ToInt32();
+ }
+ } else if (output_rep == MachineRepresentation::kWord8 ||
+ output_rep == MachineRepresentation::kWord16) {
+ DCHECK(use_info.representation() == MachineRepresentation::kWord32);
+ DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
+ return node;
}
+
if (op == nullptr) {
return TypeError(node, output_rep, output_type,
MachineRepresentation::kWord32);
}
+ return InsertConversion(node, op, use_node);
+}
+
+Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
+ Node* use_node) {
+ if (op->ControlInputCount() > 0) {
+ // If the operator can deoptimize (which means it has control
+ // input), we need to connect it to the effect and control chains.
+ Node* effect = NodeProperties::GetEffectInput(use_node);
+ Node* control = NodeProperties::GetControlInput(use_node);
+ Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
+ NodeProperties::ReplaceEffectInput(use_node, conversion);
+ return conversion;
+ }
return jsgraph()->graph()->NewNode(op, node);
}
@@ -426,7 +494,6 @@
return jsgraph()->graph()->NewNode(op, node);
}
-
Node* RepresentationChanger::GetWord64RepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type) {
if (output_rep == MachineRepresentation::kBit) {
@@ -437,18 +504,90 @@
MachineRepresentation::kWord64);
}
+Node* RepresentationChanger::GetCheckedWord32RepresentationFor(
+ Node* node, MachineRepresentation output_rep, Type* output_type,
+ Node* use_node, Truncation truncation, TypeCheckKind check) {
+ // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant
+ // does not pass the check).
+
+ // If the input is already Signed32 in Word32 representation, we do not
+ // have to do anything. (We could fold this into the big if below, but
+ // it feels nicer to have the shortcut return first).
+ if (output_rep == MachineRepresentation::kWord32 ||
+ output_type->Is(Type::Signed32())) {
+ return node;
+ }
+
+ // Select the correct X -> Word32 operator.
+ const Operator* op = nullptr;
+ if (output_rep == MachineRepresentation::kWord32) {
+ if (output_type->Is(Type::Unsigned32())) {
+ op = simplified()->CheckedUint32ToInt32();
+ }
+ } else if (output_rep == MachineRepresentation::kBit) {
+ return node; // Sloppy comparison -> word32
+ } else if (output_rep == MachineRepresentation::kFloat64) {
+ if (output_type->Is(Type::Unsigned32())) {
+ op = machine()->ChangeFloat64ToUint32();
+ } else if (output_type->Is(Type::Signed32())) {
+ op = machine()->ChangeFloat64ToInt32();
+ } else if (truncation.TruncatesToWord32()) {
+ op = machine()->TruncateFloat64ToWord32();
+ } else if (check == TypeCheckKind::kSigned32) {
+ op = simplified()->CheckedFloat64ToInt32();
+ }
+ } else if (output_rep == MachineRepresentation::kFloat32) {
+ node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
+ if (output_type->Is(Type::Unsigned32())) {
+ op = machine()->ChangeFloat64ToUint32();
+ } else if (output_type->Is(Type::Signed32())) {
+ op = machine()->ChangeFloat64ToInt32();
+ } else if (truncation.TruncatesToWord32()) {
+ op = machine()->TruncateFloat64ToWord32();
+ } else if (check == TypeCheckKind::kSigned32) {
+ op = simplified()->CheckedFloat64ToInt32();
+ }
+ } else if (output_rep == MachineRepresentation::kTagged) {
+ if (output_type->Is(Type::TaggedSigned())) {
+ op = simplified()->ChangeTaggedSignedToInt32();
+ } else if (output_type->Is(Type::Unsigned32())) {
+ op = simplified()->ChangeTaggedToUint32();
+ } else if (output_type->Is(Type::Signed32())) {
+ op = simplified()->ChangeTaggedToInt32();
+ } else if (truncation.TruncatesToWord32()) {
+ op = simplified()->TruncateTaggedToWord32();
+ } else if (check == TypeCheckKind::kSigned32) {
+ op = simplified()->CheckedTaggedToInt32();
+ }
+ }
+ if (op == nullptr) {
+ return TypeError(node, output_rep, output_type,
+ MachineRepresentation::kWord32);
+ }
+ if (op->ControlInputCount() > 0) {
+ // If the operator can deoptimize (which means it has control
+ // input), we need to connect it to the effect and control chains.
+ UNIMPLEMENTED();
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+}
const Operator* RepresentationChanger::Int32OperatorFor(
IrOpcode::Value opcode) {
switch (opcode) {
+ case IrOpcode::kSpeculativeNumberAdd: // Fall through.
case IrOpcode::kNumberAdd:
return machine()->Int32Add();
+ case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
case IrOpcode::kNumberSubtract:
return machine()->Int32Sub();
+ case IrOpcode::kSpeculativeNumberMultiply:
case IrOpcode::kNumberMultiply:
return machine()->Int32Mul();
+ case IrOpcode::kSpeculativeNumberDivide:
case IrOpcode::kNumberDivide:
return machine()->Int32Div();
+ case IrOpcode::kSpeculativeNumberModulus:
case IrOpcode::kNumberModulus:
return machine()->Int32Mod();
case IrOpcode::kNumberBitwiseOr:
@@ -458,10 +597,13 @@
case IrOpcode::kNumberBitwiseAnd:
return machine()->Word32And();
case IrOpcode::kNumberEqual:
+ case IrOpcode::kSpeculativeNumberEqual:
return machine()->Word32Equal();
case IrOpcode::kNumberLessThan:
+ case IrOpcode::kSpeculativeNumberLessThan:
return machine()->Int32LessThan();
case IrOpcode::kNumberLessThanOrEqual:
+ case IrOpcode::kSpeculativeNumberLessThanOrEqual:
return machine()->Int32LessThanOrEqual();
default:
UNREACHABLE();
@@ -469,6 +611,18 @@
}
}
+const Operator* RepresentationChanger::Int32OverflowOperatorFor(
+ IrOpcode::Value opcode) {
+ switch (opcode) {
+ case IrOpcode::kSpeculativeNumberAdd: // Fall through.
+ return simplified()->CheckedInt32Add();
+ case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
+ return simplified()->CheckedInt32Sub();
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
const Operator* RepresentationChanger::Uint32OperatorFor(
IrOpcode::Value opcode) {
@@ -477,17 +631,23 @@
return machine()->Int32Add();
case IrOpcode::kNumberSubtract:
return machine()->Int32Sub();
+ case IrOpcode::kSpeculativeNumberMultiply:
case IrOpcode::kNumberMultiply:
return machine()->Int32Mul();
+ case IrOpcode::kSpeculativeNumberDivide:
case IrOpcode::kNumberDivide:
return machine()->Uint32Div();
+ case IrOpcode::kSpeculativeNumberModulus:
case IrOpcode::kNumberModulus:
return machine()->Uint32Mod();
case IrOpcode::kNumberEqual:
+ case IrOpcode::kSpeculativeNumberEqual:
return machine()->Word32Equal();
case IrOpcode::kNumberLessThan:
+ case IrOpcode::kSpeculativeNumberLessThan:
return machine()->Uint32LessThan();
case IrOpcode::kNumberLessThanOrEqual:
+ case IrOpcode::kSpeculativeNumberLessThanOrEqual:
return machine()->Uint32LessThanOrEqual();
case IrOpcode::kNumberClz32:
return machine()->Word32Clz();
@@ -503,22 +663,64 @@
const Operator* RepresentationChanger::Float64OperatorFor(
IrOpcode::Value opcode) {
switch (opcode) {
+ case IrOpcode::kSpeculativeNumberAdd:
case IrOpcode::kNumberAdd:
return machine()->Float64Add();
+ case IrOpcode::kSpeculativeNumberSubtract:
case IrOpcode::kNumberSubtract:
return machine()->Float64Sub();
+ case IrOpcode::kSpeculativeNumberMultiply:
case IrOpcode::kNumberMultiply:
return machine()->Float64Mul();
+ case IrOpcode::kSpeculativeNumberDivide:
case IrOpcode::kNumberDivide:
return machine()->Float64Div();
+ case IrOpcode::kSpeculativeNumberModulus:
case IrOpcode::kNumberModulus:
return machine()->Float64Mod();
case IrOpcode::kNumberEqual:
+ case IrOpcode::kSpeculativeNumberEqual:
return machine()->Float64Equal();
case IrOpcode::kNumberLessThan:
+ case IrOpcode::kSpeculativeNumberLessThan:
return machine()->Float64LessThan();
case IrOpcode::kNumberLessThanOrEqual:
+ case IrOpcode::kSpeculativeNumberLessThanOrEqual:
return machine()->Float64LessThanOrEqual();
+ case IrOpcode::kNumberAbs:
+ return machine()->Float64Abs();
+ case IrOpcode::kNumberAtan:
+ return machine()->Float64Atan();
+ case IrOpcode::kNumberAtan2:
+ return machine()->Float64Atan2();
+ case IrOpcode::kNumberCos:
+ return machine()->Float64Cos();
+ case IrOpcode::kNumberExp:
+ return machine()->Float64Exp();
+ case IrOpcode::kNumberFround:
+ return machine()->TruncateFloat64ToFloat32();
+ case IrOpcode::kNumberAtanh:
+ return machine()->Float64Atanh();
+ case IrOpcode::kNumberLog:
+ return machine()->Float64Log();
+ case IrOpcode::kNumberLog1p:
+ return machine()->Float64Log1p();
+ case IrOpcode::kNumberLog2:
+ return machine()->Float64Log2();
+ case IrOpcode::kNumberLog10:
+ return machine()->Float64Log10();
+ case IrOpcode::kNumberSin:
+ return machine()->Float64Sin();
+ case IrOpcode::kNumberTan:
+ return machine()->Float64Tan();
+ case IrOpcode::kNumberSqrt:
+ return machine()->Float64Sqrt();
+ case IrOpcode::kNumberCbrt:
+ return machine()->Float64Cbrt();
+ case IrOpcode::kNumberExpm1:
+ return machine()->Float64Expm1();
+ case IrOpcode::kNumberSilenceNaN:
+ return machine()->Float64SilenceNaN();
default:
UNREACHABLE();
return nullptr;