summaryrefslogtreecommitdiff
path: root/deps/v8/src
diff options
context:
space:
mode:
authorRuben Bridgewater <ruben@bridgewater.de>2018-12-29 15:14:54 +0100
committerDaniel Bevenius <daniel.bevenius@gmail.com>2019-01-09 07:25:43 +0100
commitddbb7d7777bea03b50b0c78fa4c535081e61dde2 (patch)
tree72daa8acef49c90326b24c67301ff759138e0dd2 /deps/v8/src
parente54d11e2f64aadc74ea52185b4430afbe034f09b (diff)
downloadandroid-node-v8-ddbb7d7777bea03b50b0c78fa4c535081e61dde2.tar.gz
android-node-v8-ddbb7d7777bea03b50b0c78fa4c535081e61dde2.tar.bz2
android-node-v8-ddbb7d7777bea03b50b0c78fa4c535081e61dde2.zip
deps: cherry-pick 56f6a76 from upstream V8
Original commit message: [turbofan] Fix -0 check for subnormals. Previously we'd check `x` for -0 by testing `(1.0 / x) == -Infinity`, but this will yield the wrong results when `x` is a subnormal, i.e. really close to 0. In CSA we already perform bit checks to test for -0, so teach TurboFan to do the same for comparisons to -0 (via `Object.is`). We introduce a new NumberIsMinusZero simplified operator to handle the case where SimplifiedLowering already knows that the input is a number. Bug: chromium:903043, v8:6882 Change-Id: I0cb7c568029b461a92fc183104d5f359b4bfe7f4 Reviewed-on: https://chromium-review.googlesource.com/c/1328802 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Cr-Commit-Position: refs/heads/master@{#57382} PR-URL: https://github.com/nodejs/node/pull/25269 Refs: https://github.com/v8/v8/commit/56f6a763c27d77afbee997a50baa34996e97ba40 Fixes: https://github.com/nodejs/node/issues/25268 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'deps/v8/src')
-rw-r--r--deps/v8/src/compiler/effect-control-linearizer.cc47
-rw-r--r--deps/v8/src/compiler/effect-control-linearizer.h1
-rw-r--r--deps/v8/src/compiler/opcodes.h1
-rw-r--r--deps/v8/src/compiler/simplified-lowering.cc12
-rw-r--r--deps/v8/src/compiler/simplified-operator.cc1
-rw-r--r--deps/v8/src/compiler/simplified-operator.h1
-rw-r--r--deps/v8/src/compiler/typer.cc11
-rw-r--r--deps/v8/src/compiler/verifier.cc1
8 files changed, 60 insertions, 15 deletions
diff --git a/deps/v8/src/compiler/effect-control-linearizer.cc b/deps/v8/src/compiler/effect-control-linearizer.cc
index 97f78418d0..5f56d080d9 100644
--- a/deps/v8/src/compiler/effect-control-linearizer.cc
+++ b/deps/v8/src/compiler/effect-control-linearizer.cc
@@ -797,6 +797,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kObjectIsMinusZero:
result = LowerObjectIsMinusZero(node);
break;
+ case IrOpcode::kNumberIsMinusZero:
+ result = LowerNumberIsMinusZero(node);
+ break;
case IrOpcode::kObjectIsNaN:
result = LowerObjectIsNaN(node);
break;
@@ -2543,6 +2546,14 @@ Node* EffectControlLinearizer::LowerObjectIsSafeInteger(Node* node) {
return done.PhiAt(0);
}
+namespace {
+
+const int64_t kMinusZeroBits = bit_cast<int64_t>(-0.0);
+const int32_t kMinusZeroLoBits = static_cast<int32_t>(kMinusZeroBits);
+const int32_t kMinusZeroHiBits = static_cast<int32_t>(kMinusZeroBits >> 32);
+
+} // namespace
+
Node* EffectControlLinearizer::LowerObjectIsMinusZero(Node* node) {
Node* value = node->InputAt(0);
Node* zero = __ Int32Constant(0);
@@ -2559,15 +2570,43 @@ Node* EffectControlLinearizer::LowerObjectIsMinusZero(Node* node) {
// Check if {value} contains -0.
Node* value_value = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
- __ Goto(&done,
- __ Float64Equal(
- __ Float64Div(__ Float64Constant(1.0), value_value),
- __ Float64Constant(-std::numeric_limits<double>::infinity())));
+ if (machine()->Is64()) {
+ Node* value64 = __ BitcastFloat64ToInt64(value_value);
+ __ Goto(&done, __ Word64Equal(value64, __ Int64Constant(kMinusZeroBits)));
+ } else {
+ Node* value_lo = __ Float64ExtractLowWord32(value_value);
+ __ GotoIfNot(__ Word32Equal(value_lo, __ Int32Constant(kMinusZeroLoBits)),
+ &done, zero);
+ Node* value_hi = __ Float64ExtractHighWord32(value_value);
+ __ Goto(&done,
+ __ Word32Equal(value_hi, __ Int32Constant(kMinusZeroHiBits)));
+ }
__ Bind(&done);
return done.PhiAt(0);
}
+Node* EffectControlLinearizer::LowerNumberIsMinusZero(Node* node) {
+ Node* value = node->InputAt(0);
+
+ if (machine()->Is64()) {
+ Node* value64 = __ BitcastFloat64ToInt64(value);
+ return __ Word64Equal(value64, __ Int64Constant(kMinusZeroBits));
+ } else {
+ auto done = __ MakeLabel(MachineRepresentation::kBit);
+
+ Node* value_lo = __ Float64ExtractLowWord32(value);
+ __ GotoIfNot(__ Word32Equal(value_lo, __ Int32Constant(kMinusZeroLoBits)),
+ &done, __ Int32Constant(0));
+ Node* value_hi = __ Float64ExtractHighWord32(value);
+ __ Goto(&done,
+ __ Word32Equal(value_hi, __ Int32Constant(kMinusZeroHiBits)));
+
+ __ Bind(&done);
+ return done.PhiAt(0);
+ }
+}
+
Node* EffectControlLinearizer::LowerObjectIsNaN(Node* node) {
Node* value = node->InputAt(0);
Node* zero = __ Int32Constant(0);
diff --git a/deps/v8/src/compiler/effect-control-linearizer.h b/deps/v8/src/compiler/effect-control-linearizer.h
index fcc4cad728..20c94b3d4f 100644
--- a/deps/v8/src/compiler/effect-control-linearizer.h
+++ b/deps/v8/src/compiler/effect-control-linearizer.h
@@ -106,6 +106,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* LowerObjectIsConstructor(Node* node);
Node* LowerObjectIsDetectableCallable(Node* node);
Node* LowerObjectIsMinusZero(Node* node);
+ Node* LowerNumberIsMinusZero(Node* node);
Node* LowerObjectIsNaN(Node* node);
Node* LowerNumberIsNaN(Node* node);
Node* LowerObjectIsNonCallable(Node* node);
diff --git a/deps/v8/src/compiler/opcodes.h b/deps/v8/src/compiler/opcodes.h
index b6777ac439..ab854e6eb6 100644
--- a/deps/v8/src/compiler/opcodes.h
+++ b/deps/v8/src/compiler/opcodes.h
@@ -417,6 +417,7 @@
V(ObjectIsConstructor) \
V(ObjectIsDetectableCallable) \
V(ObjectIsMinusZero) \
+ V(NumberIsMinusZero) \
V(ObjectIsNaN) \
V(NumberIsNaN) \
V(ObjectIsNonCallable) \
diff --git a/deps/v8/src/compiler/simplified-lowering.cc b/deps/v8/src/compiler/simplified-lowering.cc
index 739f81f90d..a06cb74237 100644
--- a/deps/v8/src/compiler/simplified-lowering.cc
+++ b/deps/v8/src/compiler/simplified-lowering.cc
@@ -3008,17 +3008,7 @@ class RepresentationSelector {
VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kBit);
if (lower()) {
- // ObjectIsMinusZero(x:kRepFloat64)
- // => Float64Equal(Float64Div(1.0,x),-Infinity)
- Node* const input = node->InputAt(0);
- node->ReplaceInput(
- 0, jsgraph_->graph()->NewNode(
- lowering->machine()->Float64Div(),
- lowering->jsgraph()->Float64Constant(1.0), input));
- node->AppendInput(jsgraph_->zone(),
- jsgraph_->Float64Constant(
- -std::numeric_limits<double>::infinity()));
- NodeProperties::ChangeOp(node, lowering->machine()->Float64Equal());
+ NodeProperties::ChangeOp(node, simplified()->NumberIsMinusZero());
}
} else {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
diff --git a/deps/v8/src/compiler/simplified-operator.cc b/deps/v8/src/compiler/simplified-operator.cc
index 3aa3d30a27..a898b715a5 100644
--- a/deps/v8/src/compiler/simplified-operator.cc
+++ b/deps/v8/src/compiler/simplified-operator.cc
@@ -745,6 +745,7 @@ bool operator==(CheckMinusZeroParameters const& lhs,
V(ObjectIsConstructor, Operator::kNoProperties, 1, 0) \
V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0) \
V(ObjectIsMinusZero, Operator::kNoProperties, 1, 0) \
+ V(NumberIsMinusZero, Operator::kNoProperties, 1, 0) \
V(ObjectIsNaN, Operator::kNoProperties, 1, 0) \
V(NumberIsNaN, Operator::kNoProperties, 1, 0) \
V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0) \
diff --git a/deps/v8/src/compiler/simplified-operator.h b/deps/v8/src/compiler/simplified-operator.h
index df823fb0b0..4cea393a15 100644
--- a/deps/v8/src/compiler/simplified-operator.h
+++ b/deps/v8/src/compiler/simplified-operator.h
@@ -719,6 +719,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* ObjectIsConstructor();
const Operator* ObjectIsDetectableCallable();
const Operator* ObjectIsMinusZero();
+ const Operator* NumberIsMinusZero();
const Operator* ObjectIsNaN();
const Operator* NumberIsNaN();
const Operator* ObjectIsNonCallable();
diff --git a/deps/v8/src/compiler/typer.cc b/deps/v8/src/compiler/typer.cc
index eb357054e0..7ef20e7fae 100644
--- a/deps/v8/src/compiler/typer.cc
+++ b/deps/v8/src/compiler/typer.cc
@@ -290,6 +290,7 @@ class Typer::Visitor : public Reducer {
static Type ObjectIsConstructor(Type, Typer*);
static Type ObjectIsDetectableCallable(Type, Typer*);
static Type ObjectIsMinusZero(Type, Typer*);
+ static Type NumberIsMinusZero(Type, Typer*);
static Type ObjectIsNaN(Type, Typer*);
static Type NumberIsNaN(Type, Typer*);
static Type ObjectIsNonCallable(Type, Typer*);
@@ -597,6 +598,12 @@ Type Typer::Visitor::ObjectIsMinusZero(Type type, Typer* t) {
return Type::Boolean();
}
+Type Typer::Visitor::NumberIsMinusZero(Type type, Typer* t) {
+ if (type.Is(Type::MinusZero())) return t->singleton_true_;
+ if (!type.Maybe(Type::MinusZero())) return t->singleton_false_;
+ return Type::Boolean();
+}
+
Type Typer::Visitor::ObjectIsNaN(Type type, Typer* t) {
if (type.Is(Type::NaN())) return t->singleton_true_;
if (!type.Maybe(Type::NaN())) return t->singleton_false_;
@@ -2104,6 +2111,10 @@ Type Typer::Visitor::TypeObjectIsMinusZero(Node* node) {
return TypeUnaryOp(node, ObjectIsMinusZero);
}
+Type Typer::Visitor::TypeNumberIsMinusZero(Node* node) {
+ return TypeUnaryOp(node, NumberIsMinusZero);
+}
+
Type Typer::Visitor::TypeNumberIsFloat64Hole(Node* node) {
return Type::Boolean();
}
diff --git a/deps/v8/src/compiler/verifier.cc b/deps/v8/src/compiler/verifier.cc
index 913a2631dc..7eedd2b37b 100644
--- a/deps/v8/src/compiler/verifier.cc
+++ b/deps/v8/src/compiler/verifier.cc
@@ -1188,6 +1188,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
CheckValueInputIs(node, 0, Type::Number());
CheckTypeIs(node, Type::Boolean());
break;
+ case IrOpcode::kNumberIsMinusZero:
case IrOpcode::kNumberIsNaN:
CheckValueInputIs(node, 0, Type::Number());
CheckTypeIs(node, Type::Boolean());