Diff
Modified: trunk/JSTests/ChangeLog (231881 => 231882)
--- trunk/JSTests/ChangeLog 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/JSTests/ChangeLog 2018-05-17 01:49:24 UTC (rev 231882)
@@ -1,3 +1,13 @@
+2018-05-16 Saam Barati <sbar...@apple.com>
+
+ Constant fold CheckTypeInfoFlags on ImplementsDefaultHasInstance
+ https://bugs.webkit.org/show_bug.cgi?id=185670
+
+ Reviewed by Yusuke Suzuki.
+
+ * microbenchmarks/constant-fold-check-type-info-flags.js: Added.
+ * stress/dont-constant-fold-check-type-info-on-bound-function.js: Added.
+
2018-05-16 Commit Queue <commit-qu...@webkit.org>
Unreviewed, rolling out r231845.
Added: trunk/JSTests/microbenchmarks/constant-fold-check-type-info-flags.js (0 => 231882)
--- trunk/JSTests/microbenchmarks/constant-fold-check-type-info-flags.js (rev 0)
+++ trunk/JSTests/microbenchmarks/constant-fold-check-type-info-flags.js 2018-05-17 01:49:24 UTC (rev 231882)
@@ -0,0 +1,41 @@
+"use strict";
+
+function clobber() { }
+noInline(clobber);
+
+class C { }
+class D { }
+
+function foo(x, C) {
+ clobber();
+ return x instanceof C;
+}
+noInline(foo);
+
+function access(o) {
+ return o.foo0;
+}
+noInline(access);
+
+function theClass(i) {
+ if (i & 1)
+ return C;
+ return D;
+}
+noInline(theClass);
+
+let x = new C;
+for (let i = 0; i < 1000; ++i) {
+ let k = theClass(i);
+ if (i < 20)
+ k["foo" + i] = i;
+ if (i >= 20)
+ access(k);
+ if (i === 100)
+ k["foo" + i] = i;
+ let result = foo(x, k);
+ if (k === C && result !== true)
+ throw new Error("Bad")
+ if (k !== C && result !== false)
+ throw new Error("Bad")
+}
Added: trunk/JSTests/stress/dont-constant-fold-check-type-info-on-bound-function.js (0 => 231882)
--- trunk/JSTests/stress/dont-constant-fold-check-type-info-on-bound-function.js (rev 0)
+++ trunk/JSTests/stress/dont-constant-fold-check-type-info-on-bound-function.js 2018-05-17 01:49:24 UTC (rev 231882)
@@ -0,0 +1,17 @@
+"use strict";
+
+class C { }
+let x = new C;
+C = C.bind(this);
+
+function foo(x) {
+ x.foo;
+ return x instanceof C;
+}
+noInline(foo);
+
+for (let i = 0; i < 1000; ++i) {
+ let r = foo(x);
+ if (r !== true)
+ throw new Error("Bad")
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (231881 => 231882)
--- trunk/Source/_javascript_Core/ChangeLog 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-05-17 01:49:24 UTC (rev 231882)
@@ -1,3 +1,43 @@
+2018-05-16 Saam Barati <sbar...@apple.com>
+
+ Constant fold CheckTypeInfoFlags on ImplementsDefaultHasInstance
+ https://bugs.webkit.org/show_bug.cgi?id=185670
+
+ Reviewed by Yusuke Suzuki.
+
+ This patch makes it so that we constant fold CheckTypeInfoFlags for
+ ImplementsDefaultHasInstance inside of AI/constant folding. We constant
+ fold in three ways:
+ - When the incoming value is a constant, we just look at its inline type
+ flags. Since those flags never change after an object is created, this
+ is sound.
+ - Based on the incoming value having a finite structure set. We just iterate
+ all structures and ensure they have the bit set.
+ - Based on speculated type. To do this, I split up SpecFunction into two
+ subheaps where one is for functions that have the bit set, and one for
+ functions that don't have the bit set. The latter is currently only comprised
+ of JSBoundFunctions. To constant fold, we check that the incoming
+ value only has the SpecFunction type with ImplementsDefaultHasInstance set.
+
+ * bytecode/SpeculatedType.cpp:
+ (JSC::speculationFromClassInfo):
+ * bytecode/SpeculatedType.h:
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileCheckTypeInfoFlags):
+ * dfg/DFGStrengthReductionPhase.cpp:
+ (JSC::DFG::StrengthReductionPhase::handleNode):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::JSFunction):
+ (JSC::JSFunction::assertTypeInfoFlagInvariants):
+ * runtime/JSFunction.h:
+ (JSC::JSFunction::assertTypeInfoFlagInvariants):
+ * runtime/JSFunctionInlines.h:
+ (JSC::JSFunction::JSFunction):
+
2018-05-16 Devin Rousso <web...@devinrousso.com>
Web Inspector: create a navigation item for toggling the overlay rulers/guides
Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp (231881 => 231882)
--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp 2018-05-17 01:49:24 UTC (rev 231882)
@@ -32,6 +32,7 @@
#include "DirectArguments.h"
#include "JSArray.h"
#include "JSBigInt.h"
+#include "JSBoundFunction.h"
#include "JSCInlines.h"
#include "JSFunction.h"
#include "JSMap.h"
@@ -432,8 +433,11 @@
if (classInfo == ProxyObject::info())
return SpecProxyObject;
- if (classInfo->isSubClassOf(JSFunction::info()))
- return SpecFunction;
+ if (classInfo->isSubClassOf(JSFunction::info())) {
+ if (classInfo == JSBoundFunction::info())
+ return SpecFunctionWithNonDefaultHasInstance;
+ return SpecFunctionWithDefaultHasInstance;
+ }
if (isTypedView(classInfo->typedArrayStorageType))
return speculationFromTypedArrayType(classInfo->typedArrayStorageType);
Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.h (231881 => 231882)
--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.h 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.h 2018-05-17 01:49:24 UTC (rev 231882)
@@ -38,64 +38,66 @@
class Structure;
typedef uint64_t SpeculatedType;
-static const SpeculatedType SpecNone = 0; // We don't know anything yet.
-static const SpeculatedType SpecFinalObject = 1ull << 0; // It's definitely a JSFinalObject.
-static const SpeculatedType SpecArray = 1ull << 1; // It's definitely a JSArray.
-static const SpeculatedType SpecFunction = 1ull << 2; // It's definitely a JSFunction.
-static const SpeculatedType SpecInt8Array = 1ull << 3; // It's definitely an Int8Array or one of its subclasses.
-static const SpeculatedType SpecInt16Array = 1ull << 4; // It's definitely an Int16Array or one of its subclasses.
-static const SpeculatedType SpecInt32Array = 1ull << 5; // It's definitely an Int32Array or one of its subclasses.
-static const SpeculatedType SpecUint8Array = 1ull << 6; // It's definitely an Uint8Array or one of its subclasses.
-static const SpeculatedType SpecUint8ClampedArray = 1ull << 7; // It's definitely an Uint8ClampedArray or one of its subclasses.
-static const SpeculatedType SpecUint16Array = 1ull << 8; // It's definitely an Uint16Array or one of its subclasses.
-static const SpeculatedType SpecUint32Array = 1ull << 9; // It's definitely an Uint32Array or one of its subclasses.
-static const SpeculatedType SpecFloat32Array = 1ull << 10; // It's definitely an Uint16Array or one of its subclasses.
-static const SpeculatedType SpecFloat64Array = 1ull << 11; // It's definitely an Uint16Array or one of its subclasses.
-static const SpeculatedType SpecTypedArrayView = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array;
-static const SpeculatedType SpecDirectArguments = 1ull << 12; // It's definitely a DirectArguments object.
-static const SpeculatedType SpecScopedArguments = 1ull << 13; // It's definitely a ScopedArguments object.
-static const SpeculatedType SpecStringObject = 1ull << 14; // It's definitely a StringObject.
-static const SpeculatedType SpecRegExpObject = 1ull << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject).
-static const SpeculatedType SpecMapObject = 1ull << 16; // It's definitely a Map object or one of its subclasses.
-static const SpeculatedType SpecSetObject = 1ull << 17; // It's definitely a Set object or one of its subclasses.
-static const SpeculatedType SpecWeakMapObject = 1ull << 18; // It's definitely a WeakMap object or one of its subclasses.
-static const SpeculatedType SpecWeakSetObject = 1ull << 19; // It's definitely a WeakSet object or one of its subclasses.
-static const SpeculatedType SpecProxyObject = 1ull << 20; // It's definitely a Proxy object or one of its subclasses.
-static const SpeculatedType SpecDerivedArray = 1ull << 21; // It's definitely a DerivedArray object.
-static const SpeculatedType SpecObjectOther = 1ull << 22; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
-static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther; // Bitmask used for testing for any kind of object prediction.
-static const SpeculatedType SpecStringIdent = 1ull << 23; // It's definitely a JSString, and it's an identifier.
-static const SpeculatedType SpecStringVar = 1ull << 24; // It's definitely a JSString, and it's not an identifier.
-static const SpeculatedType SpecString = SpecStringIdent | SpecStringVar; // It's definitely a JSString.
-static const SpeculatedType SpecSymbol = 1ull << 25; // It's definitely a Symbol.
-static const SpeculatedType SpecCellOther = 1ull << 26; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString, BigInt, or Symbol.
-static const SpeculatedType SpecBoolInt32 = 1ull << 27; // It's definitely an Int32 with value 0 or 1.
-static const SpeculatedType SpecNonBoolInt32 = 1ull << 28; // 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 << 29; // 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 << 30; // It's definitely an Int52 and it's inside a double.
-static const SpeculatedType SpecNonIntAsDouble = 1ull << 31; // 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 << 32; // It's definitely a NaN that is safe to tag (i.e. pure).
-static const SpeculatedType SpecDoubleImpureNaN = 1ull << 33; // 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 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 << 34; // It's definitely a Boolean.
-static const SpeculatedType SpecOther = 1ull << 35; // 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 << 36; // It's definitely an empty value marker.
-static const SpeculatedType SpecBigInt = 1ull << 37; // It's definitely a BigInt.
-static const SpeculatedType SpecPrimitive = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue.
-static const SpeculatedType SpecCell = SpecObject | SpecString | SpecSymbol | SpecCellOther | SpecBigInt; // It's definitely a JSCell.
-static const SpeculatedType SpecHeapTop = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
-static const SpeculatedType SpecBytecodeTop = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local.
-static const SpeculatedType SpecFullTop = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers.
+static const SpeculatedType SpecNone = 0; // We don't know anything yet.
+static const SpeculatedType SpecFinalObject = 1ull << 0; // It's definitely a JSFinalObject.
+static const SpeculatedType SpecArray = 1ull << 1; // It's definitely a JSArray.
+static const SpeculatedType SpecFunctionWithDefaultHasInstance = 1ull << 2; // It's definitely a JSFunction that has its ImplementsDefaultHasInstance type info flags bit set.
+static const SpeculatedType SpecFunctionWithNonDefaultHasInstance = 1ull << 3; // It's definitely a JSFunction that does not have its ImplementsDefaultHasInstance type info flags bit set.
+static const SpeculatedType SpecFunction = SpecFunctionWithDefaultHasInstance | SpecFunctionWithNonDefaultHasInstance; // It's definitely a JSFunction.
+static const SpeculatedType SpecInt8Array = 1ull << 4; // It's definitely an Int8Array or one of its subclasses.
+static const SpeculatedType SpecInt16Array = 1ull << 5; // It's definitely an Int16Array or one of its subclasses.
+static const SpeculatedType SpecInt32Array = 1ull << 6; // It's definitely an Int32Array or one of its subclasses.
+static const SpeculatedType SpecUint8Array = 1ull << 7; // It's definitely an Uint8Array or one of its subclasses.
+static const SpeculatedType SpecUint8ClampedArray = 1ull << 8; // It's definitely an Uint8ClampedArray or one of its subclasses.
+static const SpeculatedType SpecUint16Array = 1ull << 9; // It's definitely an Uint16Array or one of its subclasses.
+static const SpeculatedType SpecUint32Array = 1ull << 10; // It's definitely an Uint32Array or one of its subclasses.
+static const SpeculatedType SpecFloat32Array = 1ull << 11; // It's definitely an Uint16Array or one of its subclasses.
+static const SpeculatedType SpecFloat64Array = 1ull << 12; // It's definitely an Uint16Array or one of its subclasses.
+static const SpeculatedType SpecTypedArrayView = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array;
+static const SpeculatedType SpecDirectArguments = 1ull << 13; // It's definitely a DirectArguments object.
+static const SpeculatedType SpecScopedArguments = 1ull << 14; // It's definitely a ScopedArguments object.
+static const SpeculatedType SpecStringObject = 1ull << 15; // It's definitely a StringObject.
+static const SpeculatedType SpecRegExpObject = 1ull << 16; // It's definitely a RegExpObject (and not any subclass of RegExpObject).
+static const SpeculatedType SpecMapObject = 1ull << 17; // It's definitely a Map object or one of its subclasses.
+static const SpeculatedType SpecSetObject = 1ull << 18; // It's definitely a Set object or one of its subclasses.
+static const SpeculatedType SpecWeakMapObject = 1ull << 19; // It's definitely a WeakMap object or one of its subclasses.
+static const SpeculatedType SpecWeakSetObject = 1ull << 20; // It's definitely a WeakSet object or one of its subclasses.
+static const SpeculatedType SpecProxyObject = 1ull << 21; // It's definitely a Proxy object or one of its subclasses.
+static const SpeculatedType SpecDerivedArray = 1ull << 22; // It's definitely a DerivedArray object.
+static const SpeculatedType SpecObjectOther = 1ull << 23; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
+static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther; // Bitmask used for testing for any kind of object prediction.
+static const SpeculatedType SpecStringIdent = 1ull << 24; // It's definitely a JSString, and it's an identifier.
+static const SpeculatedType SpecStringVar = 1ull << 25; // It's definitely a JSString, and it's not an identifier.
+static const SpeculatedType SpecString = SpecStringIdent | SpecStringVar; // It's definitely a JSString.
+static const SpeculatedType SpecSymbol = 1ull << 26; // It's definitely a Symbol.
+static const SpeculatedType SpecCellOther = 1ull << 27; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString, BigInt, or Symbol.
+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 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 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 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 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 SpecPrimitive = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue.
+static const SpeculatedType SpecCell = SpecObject | SpecString | SpecSymbol | SpecCellOther | SpecBigInt; // It's definitely a JSCell.
+static const SpeculatedType SpecHeapTop = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
+static const SpeculatedType SpecBytecodeTop = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local.
+static const SpeculatedType SpecFullTop = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers.
// SpecCellCheck is the type set representing the values that can flow through a cell check.
// On 64-bit platforms, the empty value passes a cell check. Also, ~SpecCellCheck is the type
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (231881 => 231882)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2018-05-17 01:49:24 UTC (rev 231882)
@@ -3437,7 +3437,6 @@
case CountExecution:
case CheckTierUpInLoop:
case CheckTierUpAtReturn:
- case CheckTypeInfoFlags:
case SuperSamplerBegin:
case SuperSamplerEnd:
case CheckTierUpAndOSREnter:
@@ -3446,6 +3445,43 @@
case ExitOK:
break;
+ case CheckTypeInfoFlags: {
+ const AbstractValue& abstractValue = forNode(node->child1());
+ unsigned bits = node->typeInfoOperand();
+ ASSERT(bits);
+ if (bits == ImplementsDefaultHasInstance) {
+ if (abstractValue.m_type == SpecFunctionWithDefaultHasInstance) {
+ m_state.setFoundConstants(true);
+ break;
+ }
+ }
+
+ if (JSValue value = abstractValue.value()) {
+ if (value.isCell()) {
+ // This works because if we see a cell here, we know it's fully constructed
+ // and we can read its inline type info flags. These flags don't change over the
+ // object's lifetime.
+ if ((value.asCell()->inlineTypeFlags() & bits) == bits) {
+ m_state.setFoundConstants(true);
+ break;
+ }
+ }
+ }
+
+ if (abstractValue.m_structure.isFinite()) {
+ bool ok = true;
+ abstractValue.m_structure.forEach([&] (RegisteredStructure structure) {
+ ok &= (structure->typeInfo().inlineTypeFlags() & bits) == bits;
+ });
+ if (ok) {
+ m_state.setFoundConstants(true);
+ break;
+ }
+ }
+
+ break;
+ }
+
case ParseInt: {
AbstractValue value = forNode(node->child1());
if (value.m_type && !(value.m_type & ~SpecInt32Only)) {
Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (231881 => 231882)
--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2018-05-17 01:49:24 UTC (rev 231882)
@@ -806,6 +806,46 @@
}
break;
}
+
+ case CheckTypeInfoFlags: {
+ const AbstractValue& abstractValue = m_state.forNode(node->child1());
+ unsigned bits = node->typeInfoOperand();
+ ASSERT(bits);
+ if (bits == ImplementsDefaultHasInstance) {
+ if (abstractValue.m_type == SpecFunctionWithDefaultHasInstance) {
+ changed = true;
+ node->remove(m_graph);
+ break;
+ }
+ }
+
+ if (JSValue value = abstractValue.value()) {
+ if (value.isCell()) {
+ // This works because if we see a cell here, we know it's fully constructed
+ // and we can read its inline type info flags. These flags don't change over the
+ // object's lifetime.
+ if ((value.asCell()->inlineTypeFlags() & bits) == bits) {
+ changed = true;
+ node->remove(m_graph);
+ break;
+ }
+ }
+ }
+
+ if (abstractValue.m_structure.isFinite()) {
+ bool ok = true;
+ abstractValue.m_structure.forEach([&] (RegisteredStructure structure) {
+ ok &= (structure->typeInfo().inlineTypeFlags() & bits) == bits;
+ });
+ if (ok) {
+ changed = true;
+ node->remove(m_graph);
+ break;
+ }
+ }
+
+ break;
+ }
case PhantomNewObject:
case PhantomNewFunction:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (231881 => 231882)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-05-17 01:49:24 UTC (rev 231882)
@@ -3389,6 +3389,9 @@
GPRReg baseGPR = base.gpr();
+ // FIXME: This only works for checking if a single bit is set. If we want to check more
+ // than one bit at once, we'll need to fix this:
+ // https://bugs.webkit.org/show_bug.cgi?id=185705
speculationCheck(BadTypeInfoFlags, JSValueRegs(), 0, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(node->typeInfoOperand())));
noResult(node);
Modified: trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp (231881 => 231882)
--- trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp 2018-05-17 01:49:24 UTC (rev 231882)
@@ -303,7 +303,7 @@
break;
}
- // FIXME: we should probably do this in constant folding but this currently relies on an OSR exit rule.
+ // FIXME: we should probably do this in constant folding but this currently relies on OSR exit history:
// https://bugs.webkit.org/show_bug.cgi?id=154832
case OverridesHasInstance: {
if (!m_node->child2().node()->isCellConstant())
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (231881 => 231882)
--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2018-05-17 01:49:24 UTC (rev 231882)
@@ -100,6 +100,7 @@
: Base(vm, globalObject, structure)
, m_executable()
{
+ assertTypeInfoFlagInvariants();
}
@@ -789,4 +790,16 @@
return PropertyStatus::Reified;
}
+#if !ASSERT_DISABLED
+void JSFunction::assertTypeInfoFlagInvariants()
+{
+ // If you change this, you'll need to update speculationFromClassInfo.
+ const ClassInfo* info = classInfo(*vm());
+ if (!(inlineTypeFlags() & ImplementsDefaultHasInstance))
+ RELEASE_ASSERT(info == JSBoundFunction::info());
+ else
+ RELEASE_ASSERT(info != JSBoundFunction::info());
+}
+#endif
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.h (231881 => 231882)
--- trunk/Source/_javascript_Core/runtime/JSFunction.h 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.h 2018-05-17 01:49:24 UTC (rev 231882)
@@ -208,6 +208,12 @@
PropertyStatus reifyLazyNameIfNeeded(VM&, ExecState*, PropertyName);
PropertyStatus reifyLazyBoundNameIfNeeded(VM&, ExecState*, PropertyName);
+#if ASSERT_DISABLED
+ void assertTypeInfoFlagInvariants() { }
+#else
+ void assertTypeInfoFlagInvariants();
+#endif
+
friend class LLIntOffsetsExtractor;
static EncodedJSValue argumentsGetter(ExecState*, EncodedJSValue, PropertyName);
Modified: trunk/Source/_javascript_Core/runtime/JSFunctionInlines.h (231881 => 231882)
--- trunk/Source/_javascript_Core/runtime/JSFunctionInlines.h 2018-05-17 01:37:33 UTC (rev 231881)
+++ trunk/Source/_javascript_Core/runtime/JSFunctionInlines.h 2018-05-17 01:49:24 UTC (rev 231882)
@@ -43,6 +43,7 @@
, m_executable(vm, this, executable)
, m_rareData()
{
+ assertTypeInfoFlagInvariants();
}
inline FunctionExecutable* JSFunction::jsExecutable() const