Clean up Int52 code and some bugs in it
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Apr 2019 16:06:48 +0000 (16:06 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Apr 2019 16:06:48 +0000 (16:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196639
<rdar://problem/49515757>

Reviewed by Yusuke Suzuki.

JSTests:

* stress/spec-any-int-as-double-produces-any-int52-from-int52-rep.js: Added.

Source/JavaScriptCore:

This patch fixes bugs in our Int52 code. The primary change in this patch is
adopting a segregated type lattice for Int52. Previously, for Int52 values,
we represented them with SpecInt32Only and SpecInt52Only. For an Int52,
SpecInt32Only meant that the value is in int32 range. And SpecInt52Only meant
that the is outside of the int32 range.

However, this got confusing because we reused SpecInt32Only both for JSValue
representations and Int52 representations. This actually lead to some bugs.

1. It's possible that roundtripping through Int52 representation would say
it produces the wrong type. For example, consider this program and how we
used to annotate types in AI:
a: JSConstant(10.0) => m_type is SpecAnyIntAsDouble
b: Int52Rep(@a) => m_type is SpecInt52Only
c: ValueRep(@b) => m_type is SpecAnyIntAsDouble

In AI, for the above program, we'd say that @c produces SpecAnyIntAsDouble.
However, the execution semantics are such that it'd actually produce a boxed
Int32. This patch fixes the bug where we'd say that Int52Rep over SpecAnyIntAsDouble
would produce SpecInt52Only. This is clearly wrong, as SpecAnyIntAsDouble can
mean an int value in either int32 or int52 range.

2. AsbstractValue::validateTypeAcceptingBoxedInt52 was wrong in how it
accepted Int52 values. It was wrong in two different ways:
a: If the AbstractValue's type was SpecInt52Only, and the incoming value
was a boxed double, but represented a value in int32 range, the incoming
value would incorrectly validate as being acceptable. However, we should
have rejected this value.
b: If the AbstractValue's type was SpecInt32Only, and the incoming value
was an Int32 boxed in a double, this would not validate, even though
it should have validated.

Solving 2 was easiest if we segregated out the Int52 type into its own
lattice. This patch makes a new Int52 lattice, which is composed of
SpecInt32AsInt52 and SpecNonInt32AsInt52.

The conversion rules are now really simple.

Int52 rep => JSValue rep
SpecInt32AsInt52 => SpecInt32Only
SpecNonInt32AsInt52 => SpecAnyIntAsDouble

JSValue rep => Int52 rep
SpecInt32Only => SpecInt32AsInt52
SpecAnyIntAsDouble => SpecInt52Any

With these rules, the program in (1) will now correctly report that @c
returns SpecInt32Only | SpecAnyIntAsDouble.

* bytecode/SpeculatedType.cpp:
(JSC::dumpSpeculation):
(JSC::speculationToAbbreviatedString):
(JSC::int52AwareSpeculationFromValue):
(JSC::leastUpperBoundOfStrictlyEquivalentSpeculations):
(JSC::speculationFromString):
* bytecode/SpeculatedType.h:
(JSC::isInt32SpeculationForArithmetic):
(JSC::isInt32OrBooleanSpeculationForArithmetic):
(JSC::isAnyInt52Speculation):
(JSC::isIntAnyFormat):
(JSC::isInt52Speculation): Deleted.
(JSC::isAnyIntSpeculation): Deleted.
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::fixTypeForRepresentation):
(JSC::DFG::AbstractValue::checkConsistency const):
* dfg/DFGAbstractValue.h:
(JSC::DFG::AbstractValue::isInt52Any const):
(JSC::DFG::AbstractValue::validateTypeAcceptingBoxedInt52 const):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupArithMul):
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixupGetPrototypeOf):
(JSC::DFG::FixupPhase::fixupToThis):
(JSC::DFG::FixupPhase::fixupToStringOrCallStringConstructor):
(JSC::DFG::FixupPhase::observeUseKindOnNode):
(JSC::DFG::FixupPhase::fixIntConvertingEdge):
(JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):
(JSC::DFG::FixupPhase::fixupCompareStrictEqAndSameValue):
(JSC::DFG::FixupPhase::fixupChecksInBlock):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::addShouldSpeculateInt52):
(JSC::DFG::Graph::binaryArithShouldSpeculateInt52):
(JSC::DFG::Graph::unaryArithShouldSpeculateInt52):
(JSC::DFG::Graph::addShouldSpeculateAnyInt): Deleted.
(JSC::DFG::Graph::binaryArithShouldSpeculateAnyInt): Deleted.
(JSC::DFG::Graph::unaryArithShouldSpeculateAnyInt): Deleted.
* dfg/DFGNode.h:
(JSC::DFG::Node::shouldSpeculateInt52):
(JSC::DFG::Node::shouldSpeculateAnyInt): Deleted.
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::setIntTypedArrayLoadResult):
(JSC::DFG::SpeculativeJIT::compileArithAdd):
(JSC::DFG::SpeculativeJIT::compileArithSub):
(JSC::DFG::SpeculativeJIT::compileArithNegate):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
(JSC::DFG::SpeculativeJIT::fillSpeculateInt52):
* dfg/DFGUseKind.h:
(JSC::DFG::typeFilterFor):
* dfg/DFGVariableAccessData.cpp:
(JSC::DFG::VariableAccessData::makePredictionForDoubleFormat):
(JSC::DFG::VariableAccessData::couldRepresentInt52Impl):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileArithAddOrSub):
(JSC::FTL::DFG::LowerDFGToB3::compileArithNegate):
(JSC::FTL::DFG::LowerDFGToB3::setIntTypedArrayLoadResult):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244079 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
JSTests/ChangeLog
JSTests/stress/spec-any-int-as-double-produces-any-int52-from-int52-rep.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/SpeculatedType.cpp
Source/JavaScriptCore/bytecode/SpeculatedType.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
Source/JavaScriptCore/dfg/DFGAbstractValue.h
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGUseKind.h
Source/JavaScriptCore/dfg/DFGVariableAccessData.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

index 3a7923a..e2fa36d 100644 (file)
@@ -1,3 +1,13 @@
+2019-04-09  Saam barati  <sbarati@apple.com>
+
+        Clean up Int52 code and some bugs in it
+        https://bugs.webkit.org/show_bug.cgi?id=196639
+        <rdar://problem/49515757>
+
+        Reviewed by Yusuke Suzuki.
+
+        * stress/spec-any-int-as-double-produces-any-int52-from-int52-rep.js: Added.
+
 2019-04-09  Tadeu Zagallo  <tzagallo@apple.com>
 
         ASSERTION FAILED: !scope.exception() || !hasProperty in JSObject::get
diff --git a/JSTests/stress/spec-any-int-as-double-produces-any-int52-from-int52-rep.js b/JSTests/stress/spec-any-int-as-double-produces-any-int52-from-int52-rep.js
new file mode 100644 (file)
index 0000000..829a281
--- /dev/null
@@ -0,0 +1,10 @@
+//@ runDefault("--useConcurrentJIT=0", "--validateAbstractInterpreterStateProbability=1.0", "--validateAbstractInterpreterState=1")
+
+function foo(a, v) {
+    a[0] = v + 2000000000;
+}
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i) {
+    foo({}, 1000000000);
+}
index 3f18858..7408229 100644 (file)
@@ -1,3 +1,121 @@
+2019-04-09  Saam barati  <sbarati@apple.com>
+
+        Clean up Int52 code and some bugs in it
+        https://bugs.webkit.org/show_bug.cgi?id=196639
+        <rdar://problem/49515757>
+
+        Reviewed by Yusuke Suzuki.
+
+        This patch fixes bugs in our Int52 code. The primary change in this patch is
+        adopting a segregated type lattice for Int52. Previously, for Int52 values,
+        we represented them with SpecInt32Only and SpecInt52Only. For an Int52,
+        SpecInt32Only meant that the value is in int32 range. And SpecInt52Only meant
+        that the is outside of the int32 range.
+        
+        However, this got confusing because we reused SpecInt32Only both for JSValue
+        representations and Int52 representations. This actually lead to some bugs.
+        
+        1. It's possible that roundtripping through Int52 representation would say
+        it produces the wrong type. For example, consider this program and how we
+        used to annotate types in AI:
+        a: JSConstant(10.0) => m_type is SpecAnyIntAsDouble
+        b: Int52Rep(@a) => m_type is SpecInt52Only
+        c: ValueRep(@b) => m_type is SpecAnyIntAsDouble
+        
+        In AI, for the above program, we'd say that @c produces SpecAnyIntAsDouble.
+        However, the execution semantics are such that it'd actually produce a boxed
+        Int32. This patch fixes the bug where we'd say that Int52Rep over SpecAnyIntAsDouble
+        would produce SpecInt52Only. This is clearly wrong, as SpecAnyIntAsDouble can
+        mean an int value in either int32 or int52 range.
+        
+        2. AsbstractValue::validateTypeAcceptingBoxedInt52 was wrong in how it
+        accepted Int52 values. It was wrong in two different ways:
+        a: If the AbstractValue's type was SpecInt52Only, and the incoming value
+        was a boxed double, but represented a value in int32 range, the incoming
+        value would incorrectly validate as being acceptable. However, we should
+        have rejected this value.
+        b: If the AbstractValue's type was SpecInt32Only, and the incoming value
+        was an Int32 boxed in a double, this would not validate, even though
+        it should have validated.
+        
+        Solving 2 was easiest if we segregated out the Int52 type into its own
+        lattice. This patch makes a new Int52 lattice, which is composed of
+        SpecInt32AsInt52 and SpecNonInt32AsInt52.
+        
+        The conversion rules are now really simple.
+        
+        Int52 rep => JSValue rep
+        SpecInt32AsInt52 => SpecInt32Only
+        SpecNonInt32AsInt52 => SpecAnyIntAsDouble
+        
+        JSValue rep => Int52 rep
+        SpecInt32Only => SpecInt32AsInt52
+        SpecAnyIntAsDouble => SpecInt52Any
+        
+        With these rules, the program in (1) will now correctly report that @c
+        returns SpecInt32Only | SpecAnyIntAsDouble.
+
+        * bytecode/SpeculatedType.cpp:
+        (JSC::dumpSpeculation):
+        (JSC::speculationToAbbreviatedString):
+        (JSC::int52AwareSpeculationFromValue):
+        (JSC::leastUpperBoundOfStrictlyEquivalentSpeculations):
+        (JSC::speculationFromString):
+        * bytecode/SpeculatedType.h:
+        (JSC::isInt32SpeculationForArithmetic):
+        (JSC::isInt32OrBooleanSpeculationForArithmetic):
+        (JSC::isAnyInt52Speculation):
+        (JSC::isIntAnyFormat):
+        (JSC::isInt52Speculation): Deleted.
+        (JSC::isAnyIntSpeculation): Deleted.
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGAbstractValue.cpp:
+        (JSC::DFG::AbstractValue::fixTypeForRepresentation):
+        (JSC::DFG::AbstractValue::checkConsistency const):
+        * dfg/DFGAbstractValue.h:
+        (JSC::DFG::AbstractValue::isInt52Any const):
+        (JSC::DFG::AbstractValue::validateTypeAcceptingBoxedInt52 const):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupArithMul):
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::fixupGetPrototypeOf):
+        (JSC::DFG::FixupPhase::fixupToThis):
+        (JSC::DFG::FixupPhase::fixupToStringOrCallStringConstructor):
+        (JSC::DFG::FixupPhase::observeUseKindOnNode):
+        (JSC::DFG::FixupPhase::fixIntConvertingEdge):
+        (JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):
+        (JSC::DFG::FixupPhase::fixupCompareStrictEqAndSameValue):
+        (JSC::DFG::FixupPhase::fixupChecksInBlock):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::addShouldSpeculateInt52):
+        (JSC::DFG::Graph::binaryArithShouldSpeculateInt52):
+        (JSC::DFG::Graph::unaryArithShouldSpeculateInt52):
+        (JSC::DFG::Graph::addShouldSpeculateAnyInt): Deleted.
+        (JSC::DFG::Graph::binaryArithShouldSpeculateAnyInt): Deleted.
+        (JSC::DFG::Graph::unaryArithShouldSpeculateAnyInt): Deleted.
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::shouldSpeculateInt52):
+        (JSC::DFG::Node::shouldSpeculateAnyInt): Deleted.
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::setIntTypedArrayLoadResult):
+        (JSC::DFG::SpeculativeJIT::compileArithAdd):
+        (JSC::DFG::SpeculativeJIT::compileArithSub):
+        (JSC::DFG::SpeculativeJIT::compileArithNegate):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateInt52):
+        * dfg/DFGUseKind.h:
+        (JSC::DFG::typeFilterFor):
+        * dfg/DFGVariableAccessData.cpp:
+        (JSC::DFG::VariableAccessData::makePredictionForDoubleFormat):
+        (JSC::DFG::VariableAccessData::couldRepresentInt52Impl):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileArithAddOrSub):
+        (JSC::FTL::DFG::LowerDFGToB3::compileArithNegate):
+        (JSC::FTL::DFG::LowerDFGToB3::setIntTypedArrayLoadResult):
+
 2019-04-09  Tadeu Zagallo  <tzagallo@apple.com>
 
         ASSERTION FAILED: !scope.exception() || !hasProperty in JSObject::get
index b2c4a3a..57e2cd0 100644 (file)
@@ -249,8 +249,11 @@ void dumpSpeculation(PrintStream& outStream, SpeculatedType value)
             isTop = false;
     }
     
-    if (value & SpecInt52Only)
-        strOut.print("Int52");
+    if (value & SpecInt32AsInt52)
+        strOut.print("Int32AsInt52");
+
+    if (value & SpecNonInt32AsInt52)
+        strOut.print("NonInt32AsInt52");
         
     if ((value & SpecBytecodeDouble) == SpecBytecodeDouble)
         strOut.print("BytecodeDouble");
@@ -343,10 +346,12 @@ static const char* speculationToAbbreviatedString(SpeculatedType prediction)
         return "<Int32>";
     if (isAnyIntAsDoubleSpeculation(prediction))
         return "<AnyIntAsDouble>";
-    if (isInt52Speculation(prediction))
-        return "<Int52>";
-    if (isAnyIntSpeculation(prediction))
-        return "<AnyInt>";
+    if (prediction == SpecNonInt32AsInt52)
+        return "<NonInt32AsInt52>";
+    if (prediction == SpecInt32AsInt52)
+        return "<Int32AsInt52>";
+    if (isAnyInt52Speculation(prediction))
+        return "<Int52Any>";
     if (isDoubleSpeculation(prediction))
         return "<Double>";
     if (isFullNumberSpeculation(prediction))
@@ -510,6 +515,18 @@ SpeculatedType speculationFromValue(JSValue value)
     return SpecOther;
 }
 
+SpeculatedType int52AwareSpeculationFromValue(JSValue value)
+{
+    if (!value.isAnyInt())
+        return speculationFromValue(value);
+
+    int64_t intValue = value.asAnyInt();
+    bool isI32 = static_cast<int64_t>(static_cast<int32_t>(intValue)) == intValue;
+    if (isI32)
+        return SpecInt32AsInt52;
+    return SpecNonInt32AsInt52;
+}
+
 TypedArrayType typedArrayTypeFromSpeculation(SpeculatedType type)
 {
     if (isInt8ArraySpeculation(type))
@@ -578,8 +595,8 @@ SpeculatedType speculationFromJSType(JSType type)
 SpeculatedType leastUpperBoundOfStrictlyEquivalentSpeculations(SpeculatedType type)
 {
     // SpecNonIntAsDouble includes negative zero (-0.0), which can be equal to 0 and 0.0 in the context of == and ===.
-    if (type & (SpecAnyInt | SpecAnyIntAsDouble | SpecNonIntAsDouble))
-        type |= (SpecAnyInt | SpecAnyIntAsDouble | SpecNonIntAsDouble);
+    if (type & (SpecIntAnyFormat | SpecNonIntAsDouble))
+        type |= (SpecIntAnyFormat | SpecNonIntAsDouble);
 
     if (type & SpecString)
         type |= SpecString;
@@ -803,10 +820,14 @@ SpeculatedType speculationFromString(const char* speculation)
         return SpecNonBoolInt32;
     if (!strncmp(speculation, "SpecInt32Only", strlen("SpecInt32Only")))
         return SpecInt32Only;
-    if (!strncmp(speculation, "SpecInt52Only", strlen("SpecInt52Only")))
-        return SpecInt52Only;
-    if (!strncmp(speculation, "SpecAnyInt", strlen("SpecAnyInt")))
-        return SpecAnyInt;
+    if (!strncmp(speculation, "SpecInt32AsInt52", strlen("SpecInt32AsInt52")))
+        return SpecInt32AsInt52;
+    if (!strncmp(speculation, "SpecNonInt32AsInt52", strlen("SpecNonInt32AsInt52")))
+        return SpecNonInt32AsInt52;
+    if (!strncmp(speculation, "SpecInt52Any", strlen("SpecInt52Any")))
+        return SpecInt52Any;
+    if (!strncmp(speculation, "SpecIntAnyFormat", strlen("SpecIntAnyFormat")))
+        return SpecIntAnyFormat;
     if (!strncmp(speculation, "SpecAnyIntAsDouble", strlen("SpecAnyIntAsDouble")))
         return SpecAnyIntAsDouble;
     if (!strncmp(speculation, "SpecNonIntAsDouble", strlen("SpecNonIntAsDouble")))
index 62e407c..d59bd03 100644 (file)
@@ -73,26 +73,31 @@ static const SpeculatedType SpecCellOther                         = 1ull << 27;
 static const SpeculatedType SpecBoolInt32                         = 1ull << 28; // It's definitely an Int32 with value 0 or 1.
 static const SpeculatedType SpecNonBoolInt32                      = 1ull << 29; // It's definitely an Int32 with value other than 0 or 1.
 static const SpeculatedType SpecInt32Only                         = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32.
-static const SpeculatedType SpecInt52Only                         = 1ull << 30; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.
-static const SpeculatedType SpecAnyInt                            = SpecInt32Only | SpecInt52Only; // It's something that we can do machine int arithmetic on.
-static const SpeculatedType SpecAnyIntAsDouble                    = 1ull << 31; // It's definitely an Int52 and it's inside a double.
-static const SpeculatedType SpecNonIntAsDouble                    = 1ull << 32; // It's definitely not an Int52 but it's a real number and it's a double.
+
+static const SpeculatedType SpecInt32AsInt52                      = 1ull << 30; // It's an Int52 and it can fit in an int32.
+static const SpeculatedType SpecNonInt32AsInt52                   = 1ull << 31; // It's an Int52 and it can't fit in an int32.
+static const SpeculatedType SpecInt52Any                          = SpecInt32AsInt52 | SpecNonInt32AsInt52; // It's any kind of Int52.
+
+static const SpeculatedType SpecAnyIntAsDouble                    = 1ull << 32; // It's definitely an Int52 and it's inside a double.
+static const SpeculatedType SpecNonIntAsDouble                    = 1ull << 33; // It's definitely not an Int52 but it's a real number and it's a double.
 static const SpeculatedType SpecDoubleReal                        = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double.
-static const SpeculatedType SpecDoublePureNaN                     = 1ull << 33; // It's definitely a NaN that is safe to tag (i.e. pure).
-static const SpeculatedType SpecDoubleImpureNaN                   = 1ull << 34; // It's definitely a NaN that is unsafe to tag (i.e. impure).
+static const SpeculatedType SpecDoublePureNaN                     = 1ull << 34; // It's definitely a NaN that is safe to tag (i.e. pure).
+static const SpeculatedType SpecDoubleImpureNaN                   = 1ull << 35; // It's definitely a NaN that is unsafe to tag (i.e. impure).
 static const SpeculatedType SpecDoubleNaN                         = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN.
 static const SpeculatedType SpecBytecodeDouble                    = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN.
 static const SpeculatedType SpecFullDouble                        = SpecDoubleReal | SpecDoubleNaN; // It's either a non-NaN or a NaN double.
 static const SpeculatedType SpecBytecodeRealNumber                = SpecInt32Only | SpecDoubleReal; // It's either an Int32 or a DoubleReal.
-static const SpeculatedType SpecFullRealNumber                    = SpecAnyInt | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or a Int52.
+static const SpeculatedType SpecFullRealNumber                    = SpecInt32Only | SpecInt52Any | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or an Int52.
 static const SpeculatedType SpecBytecodeNumber                    = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
-static const SpeculatedType SpecFullNumber                        = SpecAnyInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
-static const SpeculatedType SpecBoolean                           = 1ull << 35; // It's definitely a Boolean.
-static const SpeculatedType SpecOther                             = 1ull << 36; // It's definitely either Null or Undefined.
+static const SpeculatedType SpecIntAnyFormat                      = SpecInt52Any | SpecInt32Only | SpecAnyIntAsDouble;
+
+static const SpeculatedType SpecFullNumber                        = SpecIntAnyFormat | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
+static const SpeculatedType SpecBoolean                           = 1ull << 36; // It's definitely a Boolean.
+static const SpeculatedType SpecOther                             = 1ull << 37; // It's definitely either Null or Undefined.
 static const SpeculatedType SpecMisc                              = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined.
-static const SpeculatedType SpecEmpty                             = 1ull << 37; // It's definitely an empty value marker.
-static const SpeculatedType SpecBigInt                            = 1ull << 38; // It's definitely a BigInt.
-static const SpeculatedType SpecDataViewObject                    = 1ull << 39; // It's definitely a JSDataView.
+static const SpeculatedType SpecEmpty                             = 1ull << 38; // It's definitely an empty value marker.
+static const SpeculatedType SpecBigInt                            = 1ull << 39; // It's definitely a BigInt.
+static const SpeculatedType SpecDataViewObject                    = 1ull << 40; // It's definitely a JSDataView.
 static const SpeculatedType SpecPrimitive                         = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue.
 static const SpeculatedType SpecObject                            = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther | SpecDataViewObject; // Bitmask used for testing for any kind of object prediction.
 static const SpeculatedType SpecCell                              = SpecObject | SpecString | SpecSymbol | SpecCellOther | SpecBigInt; // It's definitely a JSCell.
@@ -337,12 +342,12 @@ inline bool isInt32OrBooleanSpeculation(SpeculatedType value)
 
 inline bool isInt32SpeculationForArithmetic(SpeculatedType value)
 {
-    return !(value & (SpecFullDouble | SpecInt52Only));
+    return !(value & (SpecFullDouble | SpecInt52Any));
 }
 
 inline bool isInt32OrBooleanSpeculationForArithmetic(SpeculatedType value)
 {
-    return !(value & (SpecFullDouble | SpecInt52Only));
+    return !(value & (SpecFullDouble | SpecInt52Any));
 }
 
 inline bool isInt32OrBooleanSpeculationExpectingDefined(SpeculatedType value)
@@ -350,14 +355,14 @@ inline bool isInt32OrBooleanSpeculationExpectingDefined(SpeculatedType value)
     return isInt32OrBooleanSpeculation(value & ~SpecOther);
 }
 
-inline bool isInt52Speculation(SpeculatedType value)
+inline bool isAnyInt52Speculation(SpeculatedType value)
 {
-    return value == SpecInt52Only;
+    return !!value && (value & SpecInt52Any) == value;
 }
 
-inline bool isAnyIntSpeculation(SpeculatedType value)
+inline bool isIntAnyFormat(SpeculatedType value)
 {
-    return !!value && (value & SpecAnyInt) == value;
+    return !!value && (value & SpecIntAnyFormat) == value;
 }
 
 inline bool isAnyIntAsDoubleSpeculation(SpeculatedType value)
@@ -483,6 +488,9 @@ SpeculatedType speculationFromClassInfo(const ClassInfo*);
 SpeculatedType speculationFromStructure(Structure*);
 SpeculatedType speculationFromCell(JSCell*);
 JS_EXPORT_PRIVATE SpeculatedType speculationFromValue(JSValue);
+// If it's an anyInt(), it'll return speculated types from the Int52 lattice.
+// Otherwise, it'll return types from the JSValue lattice.
+JS_EXPORT_PRIVATE SpeculatedType int52AwareSpeculationFromValue(JSValue);
 SpeculatedType speculationFromJSType(JSType);
 
 SpeculatedType speculationFromTypedArrayType(TypedArrayType); // only valid for typed views.
index 7ad450f..46a533a 100644 (file)
@@ -481,7 +481,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                     setConstant(node, jsNumber(static_cast<uint32_t>(machineInt)));
                     break;
                 }
-                setNonCellTypeForNode(node, SpecAnyInt);
+                setNonCellTypeForNode(node, SpecInt52Any);
                 break;
             }
             if (child && child.isInt32()) {
@@ -607,8 +607,9 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             setConstant(node, child);
             break;
         }
-        
-        setNonCellTypeForNode(node, SpecAnyInt);
+
+        setTypeForNode(node, forNode(node->child1()).m_type);
+        forNode(node).fixTypeForRepresentation(m_graph, node);
         break;
     }
         
@@ -667,7 +668,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                     break;
                 }
             }
-            setNonCellTypeForNode(node, SpecAnyInt);
+            setNonCellTypeForNode(node, SpecInt52Any);
             break;
         case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
@@ -767,7 +768,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                     break;
                 }
             }
-            setNonCellTypeForNode(node, SpecAnyInt);
+            setNonCellTypeForNode(node, SpecInt52Any);
             break;
         case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
@@ -830,7 +831,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                     break;
                 }
             }
-            setNonCellTypeForNode(node, SpecAnyInt);
+            setNonCellTypeForNode(node, SpecInt52Any);
             break;
         case DoubleRepUse:
             if (child && child.isNumber()) {
@@ -890,7 +891,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                     break;
                 }
             }
-            setNonCellTypeForNode(node, SpecAnyInt);
+            setNonCellTypeForNode(node, SpecInt52Any);
             break;
         case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
@@ -2130,8 +2131,8 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         case Array::Uint32Array:
             if (node->shouldSpeculateInt32())
                 setNonCellTypeForNode(node, SpecInt32Only);
-            else if (enableInt52() && node->shouldSpeculateAnyInt())
-                setNonCellTypeForNode(node, SpecAnyInt);
+            else if (node->shouldSpeculateInt52())
+                setNonCellTypeForNode(node, SpecInt52Any);
             else
                 setNonCellTypeForNode(node, SpecAnyIntAsDouble);
             break;
@@ -3875,7 +3876,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             if (data.isSigned)
                 setNonCellTypeForNode(node, SpecInt32Only);
             else
-                setNonCellTypeForNode(node, SpecAnyInt);
+                setNonCellTypeForNode(node, SpecInt52Any);
         }
         break;
     }
index 84c2085..2daaaa8 100644 (file)
@@ -134,22 +134,38 @@ void AbstractValue::fixTypeForRepresentation(Graph& graph, NodeFlags representat
             if (m_value.isInt32())
                 m_value = jsDoubleNumber(m_value.asNumber());
         }
-        if (m_type & SpecAnyInt) {
-            m_type &= ~SpecAnyInt;
+        if (m_type & SpecIntAnyFormat) {
+            m_type &= ~SpecIntAnyFormat;
             m_type |= SpecAnyIntAsDouble;
         }
         if (m_type & ~SpecFullDouble)
             DFG_CRASH(graph, node, toCString("Abstract value ", *this, " for double node has type outside SpecFullDouble.\n").data());
     } else if (representation == NodeResultInt52) {
         if (m_type & SpecAnyIntAsDouble) {
+            // AnyIntAsDouble can produce i32 or i52. SpecAnyIntAsDouble doesn't bound the magnitude of the value.
             m_type &= ~SpecAnyIntAsDouble;
-            m_type |= SpecInt52Only;
+            m_type |= SpecInt52Any;
+        }
+
+        if (m_type & SpecInt32Only) {
+            m_type &= ~SpecInt32Only;
+            m_type |= SpecInt32AsInt52;
+        }
+
+        if (m_type & ~SpecInt52Any)
+            DFG_CRASH(graph, node, toCString("Abstract value ", *this, " for int52 node has type outside SpecInt52Any.\n").data());
+
+        if (m_value) {
+            DFG_ASSERT(graph, node, m_value.isAnyInt());
+            m_type = int52AwareSpeculationFromValue(m_value);
         }
-        if (m_type & ~SpecAnyInt)
-            DFG_CRASH(graph, node, toCString("Abstract value ", *this, " for int52 node has type outside SpecAnyInt.\n").data());
     } else {
-        if (m_type & SpecInt52Only) {
-            m_type &= ~SpecInt52Only;
+        if (m_type & SpecInt32AsInt52) {
+            m_type &= ~SpecInt32AsInt52;
+            m_type |= SpecInt32Only;
+        }
+        if (m_type & SpecNonInt32AsInt52) {
+            m_type &= ~SpecNonInt32AsInt52;
             m_type |= SpecAnyIntAsDouble;
         }
         if (m_type & ~SpecBytecodeTop)
@@ -415,22 +431,21 @@ FiltrationResult AbstractValue::normalizeClarity(Graph& graph)
 void AbstractValue::checkConsistency() const
 {
     if (!(m_type & SpecCell)) {
-        ASSERT(m_structure.isClear());
-        ASSERT(!m_arrayModes);
+        RELEASE_ASSERT(m_structure.isClear());
+        RELEASE_ASSERT(!m_arrayModes);
     }
     
     if (isClear())
-        ASSERT(!m_value);
-    
-    if (!!m_value) {
-        SpeculatedType type = m_type;
-        // This relaxes the assertion below a bit, since we don't know the representation of the
-        // node.
-        if (type & SpecInt52Only)
-            type |= SpecAnyIntAsDouble;
-        ASSERT(mergeSpeculations(type, speculationFromValue(m_value)) == type);
-    }
+        RELEASE_ASSERT(!m_value);
     
+    if (m_type & SpecInt52Any) {
+        if (m_type != SpecFullTop)
+            RELEASE_ASSERT(isAnyInt52Speculation(m_type));
+    }
+
+    if (!!m_value)
+        RELEASE_ASSERT(validateTypeAcceptingBoxedInt52(m_value));
+
     // Note that it's possible for a prediction like (Final, []). This really means that
     // the value is bottom and that any code that uses the value is unreachable. But
     // we don't want to get pedantic about this as it would only increase the computational
@@ -441,7 +456,7 @@ void AbstractValue::assertIsRegistered(Graph& graph) const
 {
     m_structure.assertIsRegistered(graph);
 }
-#endif
+#endif // !ASSERT_DISABLED
 
 ResultType AbstractValue::resultType() const
 {
index a012de3..1d0b48f 100644 (file)
@@ -201,6 +201,11 @@ struct AbstractValue {
     {
         return !m_value && m_type;
     }
+
+    bool isInt52Any() const
+    {
+        return !(m_type & ~SpecInt52Any);
+    }
     
     JSValue value() const
     {
@@ -506,23 +511,19 @@ private:
     
     bool validateTypeAcceptingBoxedInt52(JSValue value) const
     {
-        if (isHeapTop())
+        if (isBytecodeTop())
             return true;
         
-        // Constant folding always represents Int52's in a double (i.e. AnyIntAsDouble).
-        // So speculationFromValue(value) for an Int52 value will return AnyIntAsDouble,
-        // and that's fine - the type validates just fine.
-        SpeculatedType type = m_type;
-        if (type & SpecInt52Only)
-            type |= SpecAnyIntAsDouble;
-        
-        if (mergeSpeculations(type, speculationFromValue(value)) != type)
-            return false;
-        
-        if (value.isEmpty()) {
-            ASSERT(m_type & SpecEmpty);
+        if (m_type & SpecInt52Any) {
+            ASSERT(!(m_type & ~SpecInt52Any));
+
+            if (mergeSpeculations(m_type, int52AwareSpeculationFromValue(value)) != m_type)
+                return false;
             return true;
         }
+
+        if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
+            return false;
         
         return true;
     }
index c81a0cf..71b91fe 100644 (file)
@@ -126,7 +126,7 @@ private:
                 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
             return;
         }
-        if (m_graph.binaryArithShouldSpeculateAnyInt(node, FixupPass)) {
+        if (m_graph.binaryArithShouldSpeculateInt52(node, FixupPass)) {
             fixEdge<Int52RepUse>(leftChild);
             fixEdge<Int52RepUse>(rightChild);
             if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()) || leftChild.node() == rightChild.node())
@@ -326,7 +326,7 @@ private:
                 break;
             }
             
-            if (m_graph.unaryArithShouldSpeculateAnyInt(node, FixupPass)) {
+            if (m_graph.unaryArithShouldSpeculateInt52(node, FixupPass)) {
                 node->setOp(ArithNegate);
                 fixEdge<Int52RepUse>(node->child1());
                 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
@@ -450,7 +450,7 @@ private:
                 node->clearFlags(NodeMustGenerate);
                 break;
             }
-            if (m_graph.unaryArithShouldSpeculateAnyInt(node, FixupPass)) {
+            if (m_graph.unaryArithShouldSpeculateInt52(node, FixupPass)) {
                 fixEdge<Int52RepUse>(node->child1());
                 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                     node->setArithMode(Arith::CheckOverflow);
@@ -681,8 +681,7 @@ private:
                 node->clearFlags(NodeMustGenerate);
                 break;
             }
-            if (enableInt52()
-                && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) {
+            if (Node::shouldSpeculateInt52(node->child1().node(), node->child2().node())) {
                 fixEdge<Int52RepUse>(node->child1());
                 fixEdge<Int52RepUse>(node->child2());
                 node->clearFlags(NodeMustGenerate);
@@ -936,7 +935,7 @@ private:
             case Array::Uint32Array:
                 if (node->shouldSpeculateInt32())
                     break;
-                if (node->shouldSpeculateAnyInt() && enableInt52())
+                if (node->shouldSpeculateInt52())
                     node->setResult(NodeResultInt52);
                 else
                     node->setResult(NodeResultDouble);
@@ -1015,7 +1014,7 @@ private:
                 fixEdge<Int32Use>(child2);
                 if (child3->shouldSpeculateInt32())
                     fixIntOrBooleanEdge(child3);
-                else if (child3->shouldSpeculateAnyInt())
+                else if (child3->shouldSpeculateInt52())
                     fixEdge<Int52RepUse>(child3);
                 else
                     fixDoubleOrBooleanEdge(child3);
@@ -1060,7 +1059,7 @@ private:
                 // just call the function when that happens. But the FTL is totally cool with those
                 // conversions.
                 if (!child->shouldSpeculateInt32()
-                    && !child->shouldSpeculateAnyInt()
+                    && !child->shouldSpeculateInt52()
                     && !(child->shouldSpeculateNumberOrBoolean() && m_graph.m_plan.isFTL()))
                     badNews = true;
             }
@@ -1081,7 +1080,7 @@ private:
                 Edge& child = m_graph.child(node, 2 + i);
                 if (child->shouldSpeculateInt32())
                     fixIntOrBooleanEdge(child);
-                else if (child->shouldSpeculateAnyInt())
+                else if (child->shouldSpeculateInt52())
                     fixEdge<Int52RepUse>(child);
                 else {
                     RELEASE_ASSERT(child->shouldSpeculateNumberOrBoolean() && m_graph.m_plan.isFTL());
@@ -1095,7 +1094,7 @@ private:
             
             if (node->arrayMode().type() == Array::Uint32Array) {
                 // NOTE: This means basically always doing Int52.
-                if (node->shouldSpeculateAnyInt() && enableInt52())
+                if (node->shouldSpeculateInt52())
                     node->setResult(NodeResultInt52);
                 else
                     node->setResult(NodeResultDouble);
@@ -1519,7 +1518,7 @@ private:
                             break;
                         }
 
-                        if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) {
+                        if (node->child1()->shouldSpeculateInt52()) {
                             insertCheck<Int52RepUse>(node->child1().node());
                             m_graph.convertToConstant(node, m_graph.freeze(globalObject->numberProtoToStringFunction()));
                             break;
@@ -2180,7 +2179,7 @@ private:
         case NumberToStringWithRadix: {
             if (node->child1()->shouldSpeculateInt32())
                 fixEdge<Int32Use>(node->child1());
-            else if (enableInt52() && node->child1()->shouldSpeculateAnyInt())
+            else if (node->child1()->shouldSpeculateInt52())
                 fixEdge<Int52RepUse>(node->child1());
             else
                 fixEdge<DoubleRepUse>(node->child1());
@@ -2614,7 +2613,7 @@ private:
                 m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->numberPrototype()));
                 return;
             }
-            if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) {
+            if (node->child1()->shouldSpeculateInt52()) {
                 insertCheck<Int52RepUse>(node->child1().node());
                 m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->numberPrototype()));
                 return;
@@ -2670,7 +2669,7 @@ private:
                 return;
             }
 
-            if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) {
+            if (node->child1()->shouldSpeculateInt52()) {
                 fixEdge<Int52RepUse>(node->child1());
                 node->convertToIdentity();
                 node->setResult(NodeResultInt52);
@@ -2904,7 +2903,7 @@ private:
             return;
         }
 
-        if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) {
+        if (node->child1()->shouldSpeculateInt52()) {
             fixEdge<Int52RepUse>(node->child1());
             node->clearFlags(NodeMustGenerate);
             return;
@@ -3225,7 +3224,7 @@ private:
                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
             break;
         case Int52RepUse:
-            if (isAnyIntSpeculation(variable->prediction()))
+            if (isAnyInt52Speculation(variable->prediction()))
                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
             break;
         case CellUse:
@@ -3316,7 +3315,7 @@ private:
         }
         
         UseKind useKind;
-        if (node->shouldSpeculateAnyInt())
+        if (node->shouldSpeculateInt52())
             useKind = Int52RepUse;
         else if (node->shouldSpeculateNumber())
             useKind = DoubleRepUse;
@@ -3413,7 +3412,7 @@ private:
             return true;
         }
         
-        if (m_graph.addShouldSpeculateAnyInt(node)) {
+        if (m_graph.addShouldSpeculateInt52(node)) {
             fixEdge<Int52RepUse>(node->child1());
             fixEdge<Int52RepUse>(node->child2());
             node->setArithMode(Arith::CheckOverflow);
@@ -3732,8 +3731,7 @@ private:
             node->setOpAndDefaultFlags(CompareStrictEq);
             return;
         }
-        if (enableInt52()
-            && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) {
+        if (Node::shouldSpeculateInt52(node->child1().node(), node->child2().node())) {
             fixEdge<Int52RepUse>(node->child1());
             fixEdge<Int52RepUse>(node->child2());
             node->setOpAndDefaultFlags(CompareStrictEq);
@@ -3973,11 +3971,11 @@ private:
                         ASSERT(indexForChecks != UINT_MAX);
                         if (edge->isAnyIntConstant()) {
                             result = m_insertionSet.insertNode(
-                                indexForChecks, SpecAnyInt, Int52Constant, originForChecks,
+                                indexForChecks, SpecInt52Any, Int52Constant, originForChecks,
                                 OpInfo(edge->constant()));
                         } else if (edge->hasDoubleResult()) {
                             result = m_insertionSet.insertNode(
-                                indexForChecks, SpecAnyInt, Int52Rep, originForChecks,
+                                indexForChecks, SpecInt52Any, Int52Rep, originForChecks,
                                 Edge(edge.node(), DoubleRepAnyIntUse));
                         } else if (edge->shouldSpeculateInt32ForArithmetic()) {
                             result = m_insertionSet.insertNode(
@@ -3985,7 +3983,7 @@ private:
                                 Edge(edge.node(), Int32Use));
                         } else {
                             result = m_insertionSet.insertNode(
-                                indexForChecks, SpecAnyInt, Int52Rep, originForChecks,
+                                indexForChecks, SpecInt52Any, Int52Rep, originForChecks,
                                 Edge(edge.node(), AnyIntUse));
                         }
 
index 99558a8..5b0bc2f 100644 (file)
@@ -284,7 +284,7 @@ public:
         return addSpeculationMode(add, pass) != DontSpeculateInt32;
     }
     
-    bool addShouldSpeculateAnyInt(Node* add)
+    bool addShouldSpeculateInt52(Node* add)
     {
         if (!enableInt52())
             return false;
@@ -295,27 +295,23 @@ public:
         if (hasExitSite(add, Int52Overflow))
             return false;
 
-        if (Node::shouldSpeculateAnyInt(left, right))
+        if (Node::shouldSpeculateInt52(left, right))
             return true;
 
-        auto shouldSpeculateAnyIntForAdd = [](Node* node) {
-            auto isAnyIntSpeculationForAdd = [](SpeculatedType value) {
-                return !!value && (value & (SpecAnyInt | SpecAnyIntAsDouble)) == value;
-            };
-
+        auto shouldSpeculateInt52ForAdd = [] (Node* node) {
             // When DoubleConstant node appears, it means that users explicitly write a constant in their code with double form instead of integer form (1.0 instead of 1).
             // In that case, we should honor this decision: using it as integer is not appropriate.
             if (node->op() == DoubleConstant)
                 return false;
-            return isAnyIntSpeculationForAdd(node->prediction());
+            return isIntAnyFormat(node->prediction());
         };
 
-        // Allow AnyInt ArithAdd only when the one side of the binary operation should be speculated AnyInt. It is a bit conservative
+        // Allow Int52 ArithAdd only when the one side of the binary operation should be speculated Int52. It is a bit conservative
         // decision. This is because Double to Int52 conversion is not so cheap. Frequent back-and-forth conversions between Double and Int52
         // rather hurt the performance. If the one side of the operation is already Int52, the cost for constructing ArithAdd becomes
         // cheap since only one Double to Int52 conversion could be required.
         // This recovers some regression in assorted tests while keeping kraken crypto improvements.
-        if (!left->shouldSpeculateAnyInt() && !right->shouldSpeculateAnyInt())
+        if (!left->shouldSpeculateInt52() && !right->shouldSpeculateInt52())
             return false;
 
         auto usesAsNumbers = [](Node* node) {
@@ -329,7 +325,7 @@ public:
         if (!usesAsNumbers(add))
             return false;
 
-        return shouldSpeculateAnyIntForAdd(left) && shouldSpeculateAnyIntForAdd(right);
+        return shouldSpeculateInt52ForAdd(left) && shouldSpeculateInt52ForAdd(right);
     }
     
     bool binaryArithShouldSpeculateInt32(Node* node, PredictionPass pass)
@@ -341,7 +337,7 @@ public:
             && node->canSpeculateInt32(node->sourceFor(pass));
     }
     
-    bool binaryArithShouldSpeculateAnyInt(Node* node, PredictionPass pass)
+    bool binaryArithShouldSpeculateInt52(Node* node, PredictionPass pass)
     {
         if (!enableInt52())
             return false;
@@ -349,7 +345,7 @@ public:
         Node* left = node->child1().node();
         Node* right = node->child2().node();
 
-        return Node::shouldSpeculateAnyInt(left, right)
+        return Node::shouldSpeculateInt52(left, right)
             && node->canSpeculateInt52(pass)
             && !hasExitSite(node, Int52Overflow);
     }
@@ -360,11 +356,11 @@ public:
             && node->canSpeculateInt32(pass);
     }
     
-    bool unaryArithShouldSpeculateAnyInt(Node* node, PredictionPass pass)
+    bool unaryArithShouldSpeculateInt52(Node* node, PredictionPass pass)
     {
         if (!enableInt52())
             return false;
-        return node->child1()->shouldSpeculateAnyInt()
+        return node->child1()->shouldSpeculateInt52()
             && node->canSpeculateInt52(pass)
             && !hasExitSite(node, Int52Overflow);
     }
index e695292..1c54485 100644 (file)
@@ -2346,9 +2346,9 @@ public:
         return isInt32OrBooleanSpeculationExpectingDefined(prediction());
     }
     
-    bool shouldSpeculateAnyInt()
+    bool shouldSpeculateInt52()
     {
-        return isAnyIntSpeculation(prediction());
+        return enableInt52() && isAnyInt52Speculation(prediction());
     }
     
     bool shouldSpeculateDouble()
@@ -2609,9 +2609,9 @@ public:
             && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
     }
     
-    static bool shouldSpeculateAnyInt(Node* op1, Node* op2)
+    static bool shouldSpeculateInt52(Node* op1, Node* op2)
     {
-        return op1->shouldSpeculateAnyInt() && op2->shouldSpeculateAnyInt();
+        return enableInt52() && op1->shouldSpeculateInt52() && op2->shouldSpeculateInt52();
     }
     
     static bool shouldSpeculateNumber(Node* op1, Node* op2)
index ef8d1af..629dbe4 100644 (file)
@@ -156,8 +156,8 @@ private:
         case GetLocal: {
             VariableAccessData* variable = node->variableAccessData();
             SpeculatedType prediction = variable->prediction();
-            if (!variable->couldRepresentInt52() && (prediction & SpecInt52Only))
-                prediction = (prediction | SpecAnyIntAsDouble) & ~SpecInt52Only;
+            if (!variable->couldRepresentInt52() && (prediction & SpecNonInt32AsInt52))
+                prediction = (prediction | SpecAnyIntAsDouble) & ~SpecNonInt32AsInt52;
             if (prediction)
                 changed |= mergePrediction(prediction);
             break;
@@ -173,7 +173,7 @@ private:
             if (node->canSpeculateInt32(m_pass))
                 changed |= mergePrediction(SpecInt32Only);
             else if (enableInt52())
-                changed |= mergePrediction(SpecAnyInt);
+                changed |= mergePrediction(SpecInt52Any);
             else
                 changed |= mergePrediction(SpecBytecodeNumber);
             break;
@@ -188,8 +188,8 @@ private:
                     && isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
                     if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
                         changed |= mergePrediction(SpecInt32Only);
-                    else if (m_graph.addShouldSpeculateAnyInt(node))
-                        changed |= mergePrediction(SpecInt52Only);
+                    else if (m_graph.addShouldSpeculateInt52(node))
+                        changed |= mergePrediction(SpecInt52Any);
                     else
                         changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
                 } else if (isStringOrStringObjectSpeculation(left) || isStringOrStringObjectSpeculation(right)) {
@@ -217,8 +217,8 @@ private:
             if (left && right) {
                 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
                     changed |= mergePrediction(SpecInt32Only);
-                else if (m_graph.addShouldSpeculateAnyInt(node))
-                    changed |= mergePrediction(SpecInt52Only);
+                else if (m_graph.addShouldSpeculateInt52(node))
+                    changed |= mergePrediction(SpecInt52Any);
                 else if (isFullNumberOrBooleanSpeculation(left) && isFullNumberOrBooleanSpeculation(right))
                     changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
                 else if (node->mayHaveNonIntResult() || (left & SpecBytecodeDouble) || (right & SpecBytecodeDouble))
@@ -238,8 +238,8 @@ private:
                     && isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
                     if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
                         changed |= mergePrediction(SpecInt32Only);
-                    else if (m_graph.addShouldSpeculateAnyInt(node))
-                        changed |= mergePrediction(SpecInt52Only);
+                    else if (m_graph.addShouldSpeculateInt52(node))
+                        changed |= mergePrediction(SpecInt52Any);
                     else
                         changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
                 } else if (node->mayHaveNonIntResult() || (left & SpecBytecodeDouble) || (right & SpecBytecodeDouble))
@@ -259,8 +259,8 @@ private:
                     && isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
                     if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
                         changed |= mergePrediction(SpecInt32Only);
-                    else if (m_graph.addShouldSpeculateAnyInt(node))
-                        changed |= mergePrediction(SpecInt52Only);
+                    else if (m_graph.addShouldSpeculateInt52(node))
+                        changed |= mergePrediction(SpecInt52Any);
                     else
                         changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
                 } else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
@@ -283,8 +283,8 @@ private:
             if (prediction) {
                 if (isInt32OrBooleanSpeculation(prediction) && node->canSpeculateInt32(m_pass))
                     changed |= mergePrediction(SpecInt32Only);
-                else if (m_graph.unaryArithShouldSpeculateAnyInt(node, m_pass))
-                    changed |= mergePrediction(SpecInt52Only);
+                else if (m_graph.unaryArithShouldSpeculateInt52(node, m_pass))
+                    changed |= mergePrediction(SpecInt52Any);
                 else if (isBytecodeNumberSpeculation(prediction))
                     changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction()));
                 else {
@@ -326,8 +326,8 @@ private:
                     && isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
                     if (m_graph.binaryArithShouldSpeculateInt32(node, m_pass))
                         changed |= mergePrediction(SpecInt32Only);
-                    else if (m_graph.binaryArithShouldSpeculateAnyInt(node, m_pass))
-                        changed |= mergePrediction(SpecInt52Only);
+                    else if (m_graph.binaryArithShouldSpeculateInt52(node, m_pass))
+                        changed |= mergePrediction(SpecInt52Any);
                     else
                         changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
                 } else if (op == ValueMul && isBigIntSpeculation(left) && isBigIntSpeculation(right))
@@ -427,7 +427,7 @@ private:
                 if (isInt32SpeculationForArithmetic(node->getHeapPrediction()) && node->op() == GetByVal)
                     changed |= mergePrediction(SpecInt32Only);
                 else if (enableInt52())
-                    changed |= mergePrediction(SpecAnyInt);
+                    changed |= mergePrediction(SpecInt52Any);
                 else
                     changed |= mergePrediction(SpecInt32Only | SpecAnyIntAsDouble);
                 break;
@@ -459,8 +459,8 @@ private:
                     break;
                 }
 
-                if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) {
-                    changed |= mergePrediction(SpecAnyInt);
+                if (node->child1()->shouldSpeculateInt52()) {
+                    changed |= mergePrediction(SpecInt52Any);
                     break;
                 }
 
@@ -567,7 +567,7 @@ private:
             if (isFullNumberSpeculation(left)
                 && isFullNumberSpeculation(right)
                 && !m_graph.addShouldSpeculateInt32(node, m_pass)
-                && !m_graph.addShouldSpeculateAnyInt(node))
+                && !m_graph.addShouldSpeculateInt52(node))
                 ballot = VoteDouble;
             else
                 ballot = VoteValue;
@@ -587,7 +587,7 @@ private:
             if (isFullNumberSpeculation(left)
                 && isFullNumberSpeculation(right)
                 && !m_graph.binaryArithShouldSpeculateInt32(node, m_pass)
-                && !m_graph.binaryArithShouldSpeculateAnyInt(node, m_pass))
+                && !m_graph.binaryArithShouldSpeculateInt52(node, m_pass))
                 ballot = VoteDouble;
             else
                 ballot = VoteValue;
@@ -643,7 +643,7 @@ private:
             if (isDoubleSpeculation(prediction))
                 node->variableAccessData()->vote(VoteDouble, weight);
             else if (!isFullNumberSpeculation(prediction)
-                || isInt32Speculation(prediction) || isAnyIntSpeculation(prediction))
+                || isInt32Speculation(prediction) || isAnyInt52Speculation(prediction))
                 node->variableAccessData()->vote(VoteValue, weight);
             break;
         }
@@ -734,10 +734,7 @@ private:
     {
         switch (m_currentNode->op()) {
         case JSConstant: {
-            SpeculatedType type = speculationFromValue(m_currentNode->asJSValue());
-            if (type == SpecAnyIntAsDouble && enableInt52())
-                type = SpecInt52Only;
-            setPrediction(type);
+            setPrediction(speculationFromValue(m_currentNode->asJSValue()));
             break;
         }
         case DoubleConstant: {
@@ -1048,7 +1045,7 @@ private:
             
         case FiatInt52: {
             RELEASE_ASSERT(enableInt52());
-            setPrediction(SpecAnyInt);
+            setPrediction(SpecInt52Any);
             break;
         }
 
index d6da198..e841cd2 100644 (file)
@@ -2919,7 +2919,8 @@ void SpeculativeJIT::setIntTypedArrayLoadResult(Node* node, GPRReg resultReg, Ty
     }
     
 #if USE(JSVALUE64)
-    if (node->shouldSpeculateAnyInt()) {
+    if (node->shouldSpeculateInt52()) {
+        ASSERT(enableInt52());
         m_jit.zeroExtend32ToPtr(resultReg, resultReg);
         strictInt52Result(resultReg, node);
         return;
@@ -4326,8 +4327,8 @@ void SpeculativeJIT::compileArithAdd(Node* node)
 
         // Will we need an overflow check? If we can prove that neither input can be
         // Int52 then the overflow check will not be necessary.
-        if (!m_state.forNode(node->child1()).couldBeType(SpecInt52Only)
-            && !m_state.forNode(node->child2()).couldBeType(SpecInt52Only)) {
+        if (!m_state.forNode(node->child1()).couldBeType(SpecNonInt32AsInt52)
+            && !m_state.forNode(node->child2()).couldBeType(SpecNonInt32AsInt52)) {
             SpeculateWhicheverInt52Operand op1(this, node->child1());
             SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
             GPRTemporary result(this, Reuse, op1);
@@ -4512,8 +4513,8 @@ void SpeculativeJIT::compileArithSub(Node* node)
 
         // Will we need an overflow check? If we can prove that neither input can be
         // Int52 then the overflow check will not be necessary.
-        if (!m_state.forNode(node->child1()).couldBeType(SpecInt52Only)
-            && !m_state.forNode(node->child2()).couldBeType(SpecInt52Only)) {
+        if (!m_state.forNode(node->child1()).couldBeType(SpecNonInt32AsInt52)
+            && !m_state.forNode(node->child2()).couldBeType(SpecNonInt32AsInt52)) {
             SpeculateWhicheverInt52Operand op1(this, node->child1());
             SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
             GPRTemporary result(this, Reuse, op1);
@@ -4596,7 +4597,7 @@ void SpeculativeJIT::compileArithNegate(Node* node)
     case Int52RepUse: {
         ASSERT(shouldCheckOverflow(node->arithMode()));
         
-        if (!m_state.forNode(node->child1()).couldBeType(SpecInt52Only)) {
+        if (!m_state.forNode(node->child1()).couldBeType(SpecNonInt32AsInt52)) {
             SpeculateWhicheverInt52Operand op1(this, node->child1());
             GPRTemporary result(this);
             GPRReg op1GPR = op1.gpr();
index 5dab08c..f83e550 100644 (file)
@@ -942,7 +942,7 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
     }
 
     case DataFormatJS: {
-        DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52Only));
+        DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52Any));
         // Check the value is an integer.
         GPRReg gpr = info.gpr();
         m_gprs.lock(gpr);
@@ -1027,7 +1027,7 @@ GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
     ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
     AbstractValue& value = m_state.forNode(edge);
 
-    m_interpreter.filter(value, SpecAnyInt);
+    m_interpreter.filter(value, SpecInt52Any);
     if (value.isClear()) {
         if (mayHaveTypeCheck(edge.useKind()))
             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
index 99aa0cd..bb43583 100644 (file)
@@ -102,7 +102,7 @@ inline SpeculatedType typeFilterFor(UseKind useKind)
     case KnownInt32Use:
         return SpecInt32Only;
     case Int52RepUse:
-        return SpecAnyInt;
+        return SpecInt52Any;
     case AnyIntUse:
         return SpecInt32Only | SpecAnyIntAsDouble;
     case NumberUse:
index 8fc4267..7985e11 100644 (file)
@@ -156,7 +156,7 @@ bool VariableAccessData::makePredictionForDoubleFormat()
     SpeculatedType type = m_prediction;
     if (type & ~SpecBytecodeNumber)
         type |= SpecDoublePureNaN;
-    if (type & SpecAnyInt)
+    if (type & (SpecInt32Only | SpecInt52Any))
         type |= SpecAnyIntAsDouble;
     return checkAndSet(m_prediction, type);
 }
@@ -180,8 +180,8 @@ bool VariableAccessData::couldRepresentInt52Impl()
         return false;
     
     // The argument-aware prediction -- which merges all of an (inlined or machine)
-    // argument's variable access datas' predictions -- must possibly be AnyInt.
-    return !(argumentAwarePrediction() & ~SpecAnyInt);
+    // argument's variable access datas' predictions -- must possibly be Int52Any.
+    return isAnyInt52Speculation(argumentAwarePrediction());
 }
 
 FlushFormat VariableAccessData::flushFormat()
index e2a4f52..62a6d33 100644 (file)
@@ -2326,8 +2326,8 @@ private:
         }
             
         case Int52RepUse: {
-            if (!abstractValue(m_node->child1()).couldBeType(SpecInt52Only)
-                && !abstractValue(m_node->child2()).couldBeType(SpecInt52Only)) {
+            if (!abstractValue(m_node->child1()).couldBeType(SpecNonInt32AsInt52)
+                && !abstractValue(m_node->child2()).couldBeType(SpecNonInt32AsInt52)) {
                 Int52Kind kind;
                 LValue left = lowWhicheverInt52(m_node->child1(), kind);
                 LValue right = lowInt52(m_node->child2(), kind);
@@ -3023,7 +3023,7 @@ private:
         }
             
         case Int52RepUse: {
-            if (!abstractValue(m_node->child1()).couldBeType(SpecInt52Only)) {
+            if (!abstractValue(m_node->child1()).couldBeType(SpecNonInt32AsInt52)) {
                 Int52Kind kind;
                 LValue value = lowWhicheverInt52(m_node->child1(), kind);
                 LValue result = m_out.neg(value);
@@ -14637,7 +14637,7 @@ private:
             return;
         }
         
-        if (m_node->shouldSpeculateAnyInt()) {
+        if (m_node->shouldSpeculateInt52()) {
             setStrictInt52(m_out.zeroExt(result, Int64));
             return;
         }