Diff
Modified: branches/safari-601.1.32-branch/Source/_javascript_Core/ChangeLog (184623 => 184624)
--- branches/safari-601.1.32-branch/Source/_javascript_Core/ChangeLog 2015-05-20 07:55:28 UTC (rev 184623)
+++ branches/safari-601.1.32-branch/Source/_javascript_Core/ChangeLog 2015-05-20 07:55:58 UTC (rev 184624)
@@ -1,3 +1,38 @@
+2015-05-20 Babak Shafiei <[email protected]>
+
+ Merge r184540.
+
+ 2015-05-18 Filip Pizlo <[email protected]>
+
+ Add SpecBoolInt32 type that means "I'm an int and I'm either 0 or 1"
+ https://bugs.webkit.org/show_bug.cgi?id=145137
+
+ Reviewed by Benjamin Poulain.
+
+ It's super useful to know if an integer value could be either zero or one. We have an
+ immediate need for this because of Int32|Boolean uses, where knowing that the Int32 is
+ either 0 or 1 means that there is no actual polymorphism if you just look at the low bit
+ (1 behaves like true, 0 behaves like false, and the low bit of 1|true is 1, and the low
+ bit of 0|false is 0).
+
+ We do this by splitting the SpecInt32 type into SpecBoolInt32 and SpecNonBoolInt32. This
+ change doesn't have any effect on behavior, yet. But it does give us the ability to
+ predict and prove when values are SpecBoolInt32; it's just we don't leverage this yet.
+
+ This is perf-neutral.
+
+ * bytecode/SpeculatedType.cpp:
+ (JSC::dumpSpeculation):
+ (JSC::speculationToAbbreviatedString):
+ (JSC::speculationFromValue):
+ * bytecode/SpeculatedType.h:
+ (JSC::isStringOrStringObjectSpeculation):
+ (JSC::isBoolInt32Speculation):
+ (JSC::isInt32Speculation):
+ (JSC::isInt32OrBooleanSpeculation):
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+
2015-05-18 Matthew Hanson <[email protected]>
Merge custom patch. rdar://problem/20950052
Modified: branches/safari-601.1.32-branch/Source/_javascript_Core/bytecode/SpeculatedType.cpp (184623 => 184624)
--- branches/safari-601.1.32-branch/Source/_javascript_Core/bytecode/SpeculatedType.cpp 2015-05-20 07:55:28 UTC (rev 184623)
+++ branches/safari-601.1.32-branch/Source/_javascript_Core/bytecode/SpeculatedType.cpp 2015-05-20 07:55:58 UTC (rev 184624)
@@ -158,10 +158,19 @@
}
}
- if (value & SpecInt32)
+ if (value == SpecInt32)
myOut.print("Int32");
- else
- isTop = false;
+ else {
+ if (value & SpecBoolInt32)
+ myOut.print("Boolint32");
+ else
+ isTop = false;
+
+ if (value & SpecNonBoolInt32)
+ myOut.print("Nonboolint32");
+ else
+ isTop = false;
+ }
if (value & SpecInt52)
myOut.print("Int52");
@@ -249,6 +258,8 @@
return "<Object>";
if (isCellSpeculation(prediction))
return "<Cell>";
+ if (isBoolInt32Speculation(prediction))
+ return "<BoolInt32>";
if (isInt32Speculation(prediction))
return "<Int32>";
if (isInt52AsDoubleSpeculation(prediction))
@@ -356,8 +367,11 @@
{
if (value.isEmpty())
return SpecEmpty;
- if (value.isInt32())
- return SpecInt32;
+ if (value.isInt32()) {
+ if (value.asInt32() & ~1)
+ return SpecNonBoolInt32;
+ return SpecBoolInt32;
+ }
if (value.isDouble()) {
double number = value.asNumber();
if (number != number)
Modified: branches/safari-601.1.32-branch/Source/_javascript_Core/bytecode/SpeculatedType.h (184623 => 184624)
--- branches/safari-601.1.32-branch/Source/_javascript_Core/bytecode/SpeculatedType.h 2015-05-20 07:55:28 UTC (rev 184623)
+++ branches/safari-601.1.32-branch/Source/_javascript_Core/bytecode/SpeculatedType.h 2015-05-20 07:55:58 UTC (rev 184624)
@@ -62,11 +62,13 @@
static const SpeculatedType SpecString = 0x00030000; // It's definitely a JSString.
static const SpeculatedType SpecCellOther = 0x00040000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=133078
static const SpeculatedType SpecCell = 0x0007ffff; // It's definitely a JSCell.
-static const SpeculatedType SpecInt32 = 0x00200000; // It's definitely an Int32.
+static const SpeculatedType SpecBoolInt32 = 0x00100000; // It's definitely an Int32 with value 0 or 1.
+static const SpeculatedType SpecNonBoolInt32 = 0x00200000; // It's definitely an Int32 with value other than 0 or 1.
+static const SpeculatedType SpecInt32 = 0x00300000; // It's definitely an Int32.
static const SpeculatedType SpecInt52 = 0x00400000; // It's definitely an Int52 and we intend it to unbox it.
-static const SpeculatedType SpecMachineInt = 0x00600000; // It's something that we can do machine int arithmetic on.
+static const SpeculatedType SpecMachineInt = 0x00700000; // It's something that we can do machine int arithmetic on.
static const SpeculatedType SpecInt52AsDouble = 0x00800000; // It's definitely an Int52 and it's inside a double.
-static const SpeculatedType SpecInteger = 0x00e00000; // It's definitely some kind of integer.
+static const SpeculatedType SpecInteger = 0x00f00000; // It's definitely some kind of integer.
static const SpeculatedType SpecNonIntAsDouble = 0x01000000; // It's definitely not an Int52 but it's a real number and it's a double.
static const SpeculatedType SpecDoubleReal = 0x01800000; // It's definitely a non-NaN double.
static const SpeculatedType SpecDoublePureNaN = 0x02000000; // It's definitely a NaN that is sae to tag (i.e. pure).
@@ -74,10 +76,10 @@
static const SpeculatedType SpecDoubleNaN = 0x06000000; // It's definitely some kind of NaN.
static const SpeculatedType SpecBytecodeDouble = 0x03800000; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN.
static const SpeculatedType SpecFullDouble = 0x07800000; // It's either a non-NaN or a NaN double.
-static const SpeculatedType SpecBytecodeRealNumber = 0x01a00000; // It's either an Int32 or a DoubleReal.
-static const SpeculatedType SpecFullRealNumber = 0x01e00000; // It's either an Int32 or a DoubleReal, or a Int52.
-static const SpeculatedType SpecBytecodeNumber = 0x03a00000; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
-static const SpeculatedType SpecFullNumber = 0x07e00000; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
+static const SpeculatedType SpecBytecodeRealNumber = 0x01b00000; // It's either an Int32 or a DoubleReal.
+static const SpeculatedType SpecFullRealNumber = 0x01f00000; // It's either an Int32 or a DoubleReal, or a Int52.
+static const SpeculatedType SpecBytecodeNumber = 0x03b00000; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
+static const SpeculatedType SpecFullNumber = 0x07f00000; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
static const SpeculatedType SpecBoolean = 0x10000000; // It's definitely a Boolean.
static const SpeculatedType SpecOther = 0x20000000; // It's definitely either Null or Undefined.
static const SpeculatedType SpecMisc = 0x30000000; // It's definitely either a boolean, Null, or Undefined.
@@ -256,9 +258,14 @@
return !!value && !(value & ~(SpecString | SpecStringObject));
}
+inline bool isBoolInt32Speculation(SpeculatedType value)
+{
+ return value == SpecBoolInt32;
+}
+
inline bool isInt32Speculation(SpeculatedType value)
{
- return value == SpecInt32;
+ return value && !(value & ~SpecInt32);
}
inline bool isInt32OrBooleanSpeculation(SpeculatedType value)
Modified: branches/safari-601.1.32-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (184623 => 184624)
--- branches/safari-601.1.32-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-05-20 07:55:28 UTC (rev 184623)
+++ branches/safari-601.1.32-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-05-20 07:55:58 UTC (rev 184624)
@@ -257,6 +257,14 @@
}
break;
}
+
+ if (node->op() == BitAnd
+ && (isBoolInt32Speculation(forNode(node->child1()).m_type) ||
+ isBoolInt32Speculation(forNode(node->child2()).m_type))) {
+ forNode(node).setType(SpecBoolInt32);
+ break;
+ }
+
forNode(node).setType(SpecInt32);
break;
}
@@ -297,7 +305,7 @@
if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
m_state.setFoundConstants(true);
if (value.m_type & SpecBoolean) {
- value.merge(SpecInt32);
+ value.merge(SpecBoolInt32);
value.filter(~SpecBoolean);
}
break;
@@ -337,6 +345,11 @@
}
}
+ if (isBooleanSpeculation(forNode(node->child1()).m_type)) {
+ forNode(node).setType(SpecBoolInt32);
+ break;
+ }
+
forNode(node).setType(SpecInt32);
break;
}