Diff
Added: branches/safari-605-branch/JSTests/stress/direct-arguments-out-of-bounds-change-structure.js (0 => 230568)
--- branches/safari-605-branch/JSTests/stress/direct-arguments-out-of-bounds-change-structure.js (rev 0)
+++ branches/safari-605-branch/JSTests/stress/direct-arguments-out-of-bounds-change-structure.js 2018-04-12 13:41:06 UTC (rev 230568)
@@ -0,0 +1,30 @@
+function foo(o)
+{
+ var theO = o;
+ var x = theO.f;
+ arguments[42];
+ return x + theO.f;
+}
+
+// Break some watchpoints.
+var o = {f:24};
+o.g = 43;
+
+noInline(foo);
+
+for (var i = 0; i < 10000; ++i) {
+ var result = foo({f:42});
+ if (result != 84)
+ throw "Error: bad result: " + result;
+}
+
+var globalO = {f:42};
+Object.prototype.__defineGetter__(42, function() {
+ delete globalO.f;
+ globalO.__defineGetter__("f", function() { return 75; });
+ return 33;
+});
+var result = foo(globalO);
+if (result != 42 + 75)
+ throw "Error: bad result at end: " + result;
+
Added: branches/safari-605-branch/JSTests/stress/new-typed-array-cse-effects.js (0 => 230568)
--- branches/safari-605-branch/JSTests/stress/new-typed-array-cse-effects.js (rev 0)
+++ branches/safari-605-branch/JSTests/stress/new-typed-array-cse-effects.js 2018-04-12 13:41:06 UTC (rev 230568)
@@ -0,0 +1,28 @@
+function foo(o, v)
+{
+ var x = o.f;
+ new Int8Array(v);
+ return x + o.f;
+}
+
+noInline(foo);
+
+// Break some watchpoints.
+var o = {f:42};
+o.f = 43;
+
+for (var i = 0; i < 10000; ++i) {
+ var result = foo({f:42}, [1, 2, 3]);
+ if (result != 84)
+ throw "Error: bad result: " + result;
+}
+
+var globalO = {f:42};
+var weirdValue = {};
+weirdValue.__defineGetter__("length", function() {
+ globalO.f = 43;
+ return 11;
+});
+var result = foo(globalO, weirdValue);
+if (result != 85)
+ throw "Error: bad result: " + result;
Added: branches/safari-605-branch/JSTests/stress/scoped-arguments-out-of-bounds-change-structure.js (0 => 230568)
--- branches/safari-605-branch/JSTests/stress/scoped-arguments-out-of-bounds-change-structure.js (rev 0)
+++ branches/safari-605-branch/JSTests/stress/scoped-arguments-out-of-bounds-change-structure.js 2018-04-12 13:41:06 UTC (rev 230568)
@@ -0,0 +1,30 @@
+function foo(o)
+{
+ var theO = (function() { return o; })();
+ var x = theO.f;
+ arguments[42];
+ return x + theO.f;
+}
+
+// Break some watchpoints.
+var o = {f:24};
+o.g = 43;
+
+noInline(foo);
+
+for (var i = 0; i < 10000; ++i) {
+ var result = foo({f:42});
+ if (result != 84)
+ throw "Error: bad result: " + result;
+}
+
+var globalO = {f:42};
+Object.prototype.__defineGetter__(42, function() {
+ delete globalO.f;
+ globalO.__defineGetter__("f", function() { return 75; });
+ return 33;
+});
+var result = foo(globalO);
+if (result != 42 + 75)
+ throw "Error: bad result at end: " + result;
+
Added: branches/safari-605-branch/JSTests/stress/string-from-char-code-change-structure-not-dead.js (0 => 230568)
--- branches/safari-605-branch/JSTests/stress/string-from-char-code-change-structure-not-dead.js (rev 0)
+++ branches/safari-605-branch/JSTests/stress/string-from-char-code-change-structure-not-dead.js 2018-04-12 13:41:06 UTC (rev 230568)
@@ -0,0 +1,31 @@
+var globalString;
+
+function foo(o, v)
+{
+ var x = o.f;
+ globalString = String.fromCharCode(v);
+ return x + o.f;
+}
+
+// Break some watchpoints.
+var o = {f:24};
+o.g = 43;
+
+noInline(foo);
+
+for (var i = 0; i < 10000; ++i) {
+ var result = foo({f:42}, {valueOf: function() { return 32; }});
+ if (result != 84)
+ throw "Error: bad result: " + result;
+}
+
+var globalO = {f:42};
+var weirdValue = {valueOf: function() {
+ delete globalO.f;
+ globalO.__defineGetter__("f", function() { return 75; });
+ return 33;
+}};
+var result = foo(globalO, weirdValue);
+if (result != 42 + 75)
+ throw "Error: bad result at end: " + result;
+
Added: branches/safari-605-branch/JSTests/stress/string-from-char-code-change-structure.js (0 => 230568)
--- branches/safari-605-branch/JSTests/stress/string-from-char-code-change-structure.js (rev 0)
+++ branches/safari-605-branch/JSTests/stress/string-from-char-code-change-structure.js 2018-04-12 13:41:06 UTC (rev 230568)
@@ -0,0 +1,29 @@
+function foo(o, v)
+{
+ var x = o.f;
+ String.fromCharCode(v);
+ return x + o.f;
+}
+
+noInline(foo);
+
+// Break some watchpoints.
+var o = {f:24};
+o.g = 43;
+
+for (var i = 0; i < 10000; ++i) {
+ var result = foo({f:42}, {valueOf: function() { return 32; }});
+ if (result != 84)
+ throw "Error: bad result: " + result;
+}
+
+var globalO = {f:42};
+var weirdValue = {valueOf: function() {
+ delete globalO.f;
+ globalO.__defineGetter__("f", function() { return 75; });
+ return 33;
+}};
+var result = foo(globalO, weirdValue);
+if (result != 42 + 75)
+ throw "Error: bad result at end: " + result;
+
Modified: branches/safari-605-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2018-04-12 13:41:06 UTC (rev 230568)
@@ -342,6 +342,7 @@
0F5CF9811E96F17F00C18692 /* AirTmpMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5CF9801E96F17D00C18692 /* AirTmpMap.h */; };
0F5CF9841E9D537700C18692 /* AirLowerStackArgs.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5CF9831E9D537500C18692 /* AirLowerStackArgs.h */; };
0F5CF9891E9ED65200C18692 /* AirStackAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5CF9871E9ED64E00C18692 /* AirStackAllocation.h */; };
+ 0F5E0FD8207C72730097F0DE /* DFGAbstractInterpreterClobberState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5E0FD6207C72710097F0DE /* DFGAbstractInterpreterClobberState.h */; };
0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F60FE901FFC37020003320A /* ExecutableToCodeBlockEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -2344,6 +2345,8 @@
0F5CF9861E9ED64E00C18692 /* AirStackAllocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirStackAllocation.cpp; path = b3/air/AirStackAllocation.cpp; sourceTree = "<group>"; };
0F5CF9871E9ED64E00C18692 /* AirStackAllocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirStackAllocation.h; path = b3/air/AirStackAllocation.h; sourceTree = "<group>"; };
0F5D085C1B8CF99D001143B4 /* DFGNodeOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNodeOrigin.cpp; path = dfg/DFGNodeOrigin.cpp; sourceTree = "<group>"; };
+ 0F5E0FD6207C72710097F0DE /* DFGAbstractInterpreterClobberState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractInterpreterClobberState.h; path = dfg/DFGAbstractInterpreterClobberState.h; sourceTree = "<group>"; };
+ 0F5E0FD7207C72710097F0DE /* DFGAbstractInterpreterClobberState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractInterpreterClobberState.cpp; path = dfg/DFGAbstractInterpreterClobberState.cpp; sourceTree = "<group>"; };
0F5EF91B16878F78003E5C25 /* JITThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITThunks.cpp; sourceTree = "<group>"; };
0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; };
0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnconditionalFinalizer.h; sourceTree = "<group>"; };
@@ -7065,6 +7068,8 @@
A77A423617A0BBFD00A8DB81 /* DFGAbstractHeap.cpp */,
A77A423717A0BBFD00A8DB81 /* DFGAbstractHeap.h */,
A704D8FE17A0BAA8006BA554 /* DFGAbstractInterpreter.h */,
+ 0F5E0FD7207C72710097F0DE /* DFGAbstractInterpreterClobberState.cpp */,
+ 0F5E0FD6207C72710097F0DE /* DFGAbstractInterpreterClobberState.h */,
A704D8FF17A0BAA8006BA554 /* DFGAbstractInterpreterInlines.h */,
0F55C19317276E4600CEABFD /* DFGAbstractValue.cpp */,
0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */,
@@ -8159,6 +8164,7 @@
8BC064921E1ADCC400B2B8CA /* AsyncGeneratorPrototype.h in Headers */,
8B3BF5E41E3D368B0076A87A /* AsyncGeneratorPrototype.lut.h in Headers */,
8BC064961E1D845C00B2B8CA /* AsyncIteratorPrototype.h in Headers */,
+ 0F5E0FD8207C72730097F0DE /* DFGAbstractInterpreterClobberState.h in Headers */,
6A38CFAA1E32B5AB0060206F /* AsyncStackTrace.h in Headers */,
0F7CF9571DC125900098CC12 /* AtomicsObject.h in Headers */,
0FB4677F1FDDA6E9003FCB09 /* AtomIndices.h in Headers */,
Modified: branches/safari-605-branch/Source/_javascript_Core/Sources.txt (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/Sources.txt 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/Sources.txt 2018-04-12 13:41:06 UTC (rev 230568)
@@ -271,6 +271,7 @@
debugger/DebuggerScope.cpp
dfg/DFGAbstractHeap.cpp
+dfg/DFGAbstractInterpreterClobberState.cpp
dfg/DFGAbstractValue.cpp
dfg/DFGAdaptiveInferredPropertyValueWatchpoint.cpp
dfg/DFGAdaptiveStructureWatchpoint.cpp
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreter.h (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreter.h 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreter.h 2018-04-12 13:41:06 UTC (rev 230568)
@@ -150,14 +150,16 @@
private:
void clobberWorld(const CodeOrigin&, unsigned indexInBlock);
+ void didFoldClobberWorld();
template<typename Functor>
void forAllValues(unsigned indexInBlock, Functor&);
void clobberStructures(unsigned indexInBlock);
+ void didFoldClobberStructures();
+
void observeTransition(unsigned indexInBlock, RegisteredStructure from, RegisteredStructure to);
void observeTransitions(unsigned indexInBlock, const TransitionVector&);
- void setDidClobber();
enum BooleanResult {
UnknownBooleanResult,
Added: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterClobberState.cpp (0 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterClobberState.cpp (rev 0)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterClobberState.cpp 2018-04-12 13:41:06 UTC (rev 230568)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DFGAbstractInterpreterClobberState.h"
+
+#include <wtf/PrintStream.h>
+
+namespace WTF {
+
+void printInternal(PrintStream& out, JSC::DFG::AbstractInterpreterClobberState clobberState)
+{
+ switch (clobberState) {
+ case JSC::DFG::AbstractInterpreterClobberState::NotClobbered:
+ out.print("NotClobbered");
+ return;
+ case JSC::DFG::AbstractInterpreterClobberState::FoldedClobber:
+ out.print("FoldedClobber");
+ return;
+ case JSC::DFG::AbstractInterpreterClobberState::ObservedTransitions:
+ out.print("ObservedTransitions");
+ return;
+ case JSC::DFG::AbstractInterpreterClobberState::ClobberedStructures:
+ out.print("ClobberedStructures");
+ return;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
Added: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterClobberState.h (0 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterClobberState.h (rev 0)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterClobberState.h 2018-04-12 13:41:06 UTC (rev 230568)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <cstdint>
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+enum class AbstractInterpreterClobberState : uint8_t {
+ NotClobbered,
+ FoldedClobber,
+ ObservedTransitions,
+ ClobberedStructures
+};
+
+inline AbstractInterpreterClobberState mergeClobberStates(AbstractInterpreterClobberState a, AbstractInterpreterClobberState b)
+{
+ uint8_t aInt = static_cast<uint8_t>(a);
+ uint8_t bInt = static_cast<uint8_t>(b);
+ return static_cast<AbstractInterpreterClobberState>(std::max(aInt, bInt));
+}
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+class PrintStream;
+
+void printInternal(PrintStream&, JSC::DFG::AbstractInterpreterClobberState);
+
+} // namespace WTF
+
+#endif // ENABLE(DFG_JIT)
+
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2018-04-12 13:41:06 UTC (rev 230568)
@@ -29,6 +29,7 @@
#include "ArrayConstructor.h"
#include "DFGAbstractInterpreter.h"
+#include "DFGAbstractInterpreterClobberState.h"
#include "DOMJITGetterSetter.h"
#include "DOMJITSignature.h"
#include "GetByIdStatus.h"
@@ -96,7 +97,7 @@
ASSERT(m_state.block());
ASSERT(m_state.isValid());
- m_state.setDidClobber(false);
+ m_state.setClobberState(AbstractInterpreterClobberState::NotClobbered);
}
template<typename AbstractStateType>
@@ -328,7 +329,16 @@
// FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
// itself into a straight-line sequence of GetStack/PutStack.
// https://bugs.webkit.org/show_bug.cgi?id=143071
- clobberWorld(node->origin.semantic, clobberLimit);
+ switch (node->op()) {
+ case LoadVarargs:
+ clobberWorld(node->origin.semantic, clobberLimit);
+ break;
+ case ForwardVarargs:
+ break;
+ default:
+ DFG_CRASH(m_graph, node, "Bad opcode");
+ break;
+ }
LoadVarargsData* data = ""
m_state.variables().operand(data->count).setType(SpecInt32Only);
for (unsigned i = data->limit - 1; i--;)
@@ -608,6 +618,14 @@
case ArithClz32: {
JSValue operand = forNode(node->child1()).value();
if (std::optional<double> number = operand.toNumberFromPrimitive()) {
+ switch (node->child1().useKind()) {
+ case Int32Use:
+ case KnownInt32Use:
+ break;
+ default:
+ didFoldClobberWorld();
+ break;
+ }
uint32_t value = toUInt32(*number);
setConstant(node, jsNumber(clz32(value)));
break;
@@ -1015,6 +1033,9 @@
case ArithTrunc: {
JSValue operand = forNode(node->child1()).value();
if (std::optional<double> number = operand.toNumberFromPrimitive()) {
+ if (node->child1().useKind() != DoubleRepUse)
+ didFoldClobberWorld();
+
double roundedValue = 0;
if (node->op() == ArithRound)
roundedValue = jsRound(*number);
@@ -1490,6 +1511,11 @@
case CompareGreater:
case CompareGreaterEq:
case CompareEq: {
+ bool isClobbering = node->isBinaryUseKind(UntypedUse);
+
+ if (isClobbering)
+ didFoldClobberWorld();
+
JSValue leftConst = forNode(node->child1()).value();
JSValue rightConst = forNode(node->child2()).value();
if (leftConst && rightConst) {
@@ -1611,7 +1637,7 @@
}
}
- if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse)
+ if (isClobbering)
clobberWorld(node->origin.semantic, clobberLimit);
forNode(node).setType(SpecBoolean);
break;
@@ -1698,6 +1724,16 @@
break;
case StringFromCharCode:
+ switch (node->child1().useKind()) {
+ case Int32Use:
+ break;
+ case UntypedUse:
+ clobberWorld(node->origin.semantic, clobberLimit);
+ break;
+ default:
+ DFG_CRASH(m_graph, node, "Bad use kind");
+ break;
+ }
forNode(node).setType(m_graph, SpecString);
break;
@@ -1758,6 +1794,8 @@
break;
case Array::DirectArguments:
case Array::ScopedArguments:
+ if (node->arrayMode().isOutOfBounds())
+ clobberWorld(node->origin.semantic, clobberLimit);
forNode(node).makeHeapTop();
break;
case Array::Int32:
@@ -2029,6 +2067,7 @@
case ToPrimitive: {
JSValue childConst = forNode(node->child1()).value();
if (childConst && childConst.isNumber()) {
+ didFoldClobberWorld();
setConstant(node, childConst);
break;
}
@@ -2037,12 +2076,12 @@
if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
m_state.setFoundConstants(true);
+ didFoldClobberWorld();
forNode(node) = forNode(node->child1());
break;
}
clobberWorld(node->origin.semantic, clobberLimit);
-
forNode(node).setType(m_graph, SpecHeapTop & ~SpecObject);
break;
}
@@ -2050,6 +2089,7 @@
case ToNumber: {
JSValue childConst = forNode(node->child1()).value();
if (childConst && childConst.isNumber()) {
+ didFoldClobberWorld();
setConstant(node, childConst);
break;
}
@@ -2058,6 +2098,7 @@
if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
m_state.setFoundConstants(true);
+ didFoldClobberWorld();
forNode(node) = forNode(node->child1());
break;
}
@@ -2101,6 +2142,7 @@
int32_t radix = radixValue.asInt32();
if (2 <= radix && radix <= 36) {
m_state.setFoundConstants(true);
+ didFoldClobberWorld();
forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
break;
}
@@ -2144,8 +2186,17 @@
break;
case Spread:
- if (!m_graph.canDoFastSpread(node, forNode(node->child1())))
- clobberWorld(node->origin.semantic, clobberLimit);
+ switch (node->child1()->op()) {
+ case PhantomNewArrayBuffer:
+ case PhantomCreateRest:
+ break;
+ default:
+ if (!m_graph.canDoFastSpread(node, forNode(node->child1())))
+ clobberWorld(node->origin.semantic, clobberLimit);
+ else
+ didFoldClobberWorld();
+ break;
+ }
forNode(node).set(
m_graph, m_vm.fixedArrayStructure.get());
@@ -2235,6 +2286,8 @@
if (!(source.m_type & ~SpecObject)) {
m_state.setFoundConstants(true);
+ if (node->op() == ToObject)
+ didFoldClobberWorld();
destination = source;
break;
}
@@ -2258,7 +2311,6 @@
case PhantomNewArrayWithSpread:
case PhantomNewArrayBuffer:
case BottomValue:
- m_state.setDidClobber(true); // Prevent constant folding.
// This claims to return bottom.
break;
@@ -2463,11 +2515,6 @@
case GetByIdDirectFlush:
case GetById:
case GetByIdFlush: {
- if (!node->prediction()) {
- m_state.setIsValid(false);
- break;
- }
-
AbstractValue& value = forNode(node->child1());
if (value.m_structure.isFinite()
&& (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
@@ -2487,6 +2534,7 @@
value, uid, status[i].offset(), m_state.structureClobberState()));
}
m_state.setFoundConstants(true);
+ didFoldClobberWorld();
forNode(node) = result;
break;
}
@@ -2626,9 +2674,10 @@
case PutStructure:
if (!forNode(node->child1()).m_structure.isClear()) {
- if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
+ if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next) {
+ didFoldClobberStructures();
m_state.setFoundConstants(true);
- else {
+ } else {
observeTransition(
clobberLimit, node->transition()->previous, node->transition()->next);
forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
@@ -2641,6 +2690,8 @@
case NukeStructureAndSetButterfly:
// FIXME: We don't model the fact that the structureID is nuked, simply because currently
// nobody would currently benefit from having that information. But it's a bug nonetheless.
+ if (node->op() == NukeStructureAndSetButterfly)
+ didFoldClobberStructures();
forNode(node).clear(); // The result is not a JS value.
break;
case CheckSubClass: {
@@ -2740,6 +2791,7 @@
}
case Arrayify: {
if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
+ didFoldClobberStructures();
m_state.setFoundConstants(true);
break;
}
@@ -2831,6 +2883,15 @@
});
if (prototype && canFold) {
+ switch (node->child1().useKind()) {
+ case ArrayUse:
+ case FunctionUse:
+ case FinalObjectUse:
+ break;
+ default:
+ didFoldClobberWorld();
+ break;
+ }
setConstant(node, *m_graph.freeze(prototype));
break;
}
@@ -2962,6 +3023,9 @@
AbstractValue originalValue = forNode(node->child2());
AbstractValue resultingValue;
+ if (node->multiPutByOffsetData().writesStructures())
+ didFoldClobberStructures();
+
for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
RegisteredStructureSet thisSet = *m_graph.addStructureSet(variant.oldStructure());
@@ -3092,6 +3156,7 @@
if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
m_state.setFoundConstants(true);
+ didFoldClobberWorld();
observeTransitions(clobberLimit, transitions);
if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
m_state.setIsValid(false);
@@ -3319,6 +3384,8 @@
if (radix.isNumber()
&& (radix.asNumber() == 0 || radix.asNumber() == 10)) {
m_state.setFoundConstants(true);
+ if (node->child1().useKind() == UntypedUse)
+ didFoldClobberWorld();
forNode(node).setType(SpecInt32Only);
break;
}
@@ -3422,6 +3489,12 @@
}
template<typename AbstractStateType>
+void AbstractInterpreter<AbstractStateType>::didFoldClobberWorld()
+{
+ didFoldClobberStructures();
+}
+
+template<typename AbstractStateType>
template<typename Functor>
void AbstractInterpreter<AbstractStateType>::forAllValues(
unsigned clobberLimit, Functor& functor)
@@ -3454,10 +3527,17 @@
void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
{
forAllValues(clobberLimit, AbstractValue::clobberStructuresFor);
- setDidClobber();
+ m_state.mergeClobberState(AbstractInterpreterClobberState::ClobberedStructures);
+ m_state.setStructureClobberState(StructuresAreClobbered);
}
template<typename AbstractStateType>
+void AbstractInterpreter<AbstractStateType>::didFoldClobberStructures()
+{
+ m_state.mergeClobberState(AbstractInterpreterClobberState::FoldedClobber);
+}
+
+template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::observeTransition(
unsigned clobberLimit, RegisteredStructure from, RegisteredStructure to)
{
@@ -3465,6 +3545,8 @@
forAllValues(clobberLimit, transitionObserver);
ASSERT(!from->dfgShouldWatch()); // We don't need to claim to be in a clobbered state because 'from' was never watchable (during the time we were compiling), hence no constants ever introduced into the DFG IR that ever had a watchable structure would ever have the same structure as from.
+
+ m_state.mergeClobberState(AbstractInterpreterClobberState::ObservedTransitions);
}
template<typename AbstractStateType>
@@ -3471,6 +3553,9 @@
void AbstractInterpreter<AbstractStateType>::observeTransitions(
unsigned clobberLimit, const TransitionVector& vector)
{
+ if (vector.isEmpty())
+ return;
+
AbstractValue::TransitionsObserver transitionsObserver(vector);
forAllValues(clobberLimit, transitionsObserver);
@@ -3479,13 +3564,8 @@
for (unsigned i = vector.size(); i--;)
ASSERT(!vector[i].previous->dfgShouldWatch());
}
-}
-template<typename AbstractStateType>
-void AbstractInterpreter<AbstractStateType>::setDidClobber()
-{
- m_state.setDidClobber(true);
- m_state.setStructureClobberState(StructuresAreClobbered);
+ m_state.mergeClobberState(AbstractInterpreterClobberState::ObservedTransitions);
}
template<typename AbstractStateType>
@@ -3585,6 +3665,8 @@
{
JSValue child = forNode(node->child1()).value();
if (std::optional<double> number = child.toNumberFromPrimitive()) {
+ if (node->child1().useKind() != DoubleRepUse)
+ didFoldClobberWorld();
setConstant(node, jsDoubleNumber(equivalentFunction(*number)));
return;
}
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAtTailAbstractState.h (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAtTailAbstractState.h 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGAtTailAbstractState.h 2018-04-12 13:41:06 UTC (rev 230568)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,6 +27,7 @@
#if ENABLE(DFG_JIT)
+#include "DFGAbstractInterpreterClobberState.h"
#include "DFGAbstractValue.h"
#include "DFGBasicBlock.h"
#include "DFGBlockMap.h"
@@ -59,7 +60,8 @@
StructureClobberState structureClobberState() const { return m_block->cfaStructureClobberStateAtTail; }
- void setDidClobber(bool) { }
+ void setClobberState(AbstractInterpreterClobberState) { }
+ void mergeClobberState(AbstractInterpreterClobberState) { }
void setStructureClobberState(StructureClobberState state) { RELEASE_ASSERT(state == m_block->cfaStructureClobberStateAtTail); }
void setIsValid(bool isValid) { m_block->cfaDidFinish = isValid; }
void setBranchDirection(BranchDirection) { }
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGCFAPhase.cpp (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGCFAPhase.cpp 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGCFAPhase.cpp 2018-04-12 13:41:06 UTC (rev 230568)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,6 +29,7 @@
#if ENABLE(DFG_JIT)
#include "DFGAbstractInterpreterInlines.h"
+#include "DFGClobberSet.h"
#include "DFGGraph.h"
#include "DFGInPlaceAbstractState.h"
#include "DFGPhase.h"
@@ -163,8 +164,8 @@
dataLog(" head regs: ", nodeValuePairListDump(block->ssa->valuesAtHead), "\n");
}
for (unsigned i = 0; i < block->size(); ++i) {
+ Node* node = block->at(i);
if (m_verbose) {
- Node* node = block->at(i);
dataLogF(" %s @%u: ", Graph::opName(node->op()), node->index());
if (!safeToExecute(m_state, m_graph, node))
@@ -179,6 +180,9 @@
dataLogF(" Expect OSR exit.\n");
break;
}
+
+ if (m_state.didClobberOrFolded() != writesOverlap(m_graph, node, JSCell_structureID))
+ DFG_CRASH(m_graph, node, toCString("AI-clobberize disagreement; AI says ", m_state.clobberState(), " while clobberize says ", writeSet(m_graph, node)).data());
}
if (m_verbose) {
dataLogF(" tail regs: ");
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGClobberSet.cpp (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGClobberSet.cpp 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGClobberSet.cpp 2018-04-12 13:41:06 UTC (rev 230568)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -158,6 +158,13 @@
clobberize(graph, node, addRead, addWrite, noOp);
}
+ClobberSet writeSet(Graph& graph, Node* node)
+{
+ ClobberSet result;
+ addWrites(graph, node, result);
+ return result;
+}
+
bool readsOverlap(Graph& graph, Node* node, ClobberSet& readSet)
{
ClobberSetOverlaps addRead(readSet);
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGClobberSet.h (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGClobberSet.h 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGClobberSet.h 2018-04-12 13:41:06 UTC (rev 230568)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -113,6 +113,8 @@
void addWrites(Graph&, Node*, ClobberSet&);
void addReadsAndWrites(Graph&, Node*, ClobberSet& reads, ClobberSet& writes);
+ClobberSet writeSet(Graph&, Node*);
+
bool readsOverlap(Graph&, Node*, ClobberSet&);
bool writesOverlap(Graph&, Node*, ClobberSet&);
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGClobberize.h (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGClobberize.h 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGClobberize.h 2018-04-12 13:41:06 UTC (rev 230568)
@@ -953,10 +953,29 @@
return;
case Array::ArrayStorage:
+ if (node->arrayMode().isOutOfBounds()) {
+ read(World);
+ write(Heap);
+ return;
+ }
+ read(Butterfly_publicLength);
+ read(Butterfly_vectorLength);
+ read(ArrayStorageProperties);
+ write(ArrayStorageProperties);
+ if (node->arrayMode().mayStoreToHole())
+ write(Butterfly_publicLength);
+ return;
+
case Array::SlowPutArrayStorage:
- // Give up on life for now.
- read(World);
- write(Heap);
+ if (node->arrayMode().mayStoreToHole()) {
+ read(World);
+ write(Heap);
+ return;
+ }
+ read(Butterfly_publicLength);
+ read(Butterfly_vectorLength);
+ read(ArrayStorageProperties);
+ write(ArrayStorageProperties);
return;
case Array::Int8Array:
@@ -1300,11 +1319,25 @@
return;
case NewArrayWithSize:
- case NewTypedArray:
read(HeapObjectCount);
write(HeapObjectCount);
return;
+ case NewTypedArray:
+ switch (node->child1().useKind()) {
+ case Int32Use:
+ read(HeapObjectCount);
+ write(HeapObjectCount);
+ return;
+ case UntypedUse:
+ read(World);
+ write(Heap);
+ return;
+ default:
+ DFG_CRASH(graph, node, "Bad use kind");
+ }
+ break;
+
case NewArrayWithSpread: {
// This also reads from JSFixedArray's data store, but we don't have any way of describing that yet.
read(HeapObjectCount);
@@ -1522,7 +1555,7 @@
case CompareBelowEq:
def(PureValue(node));
return;
-
+
case CompareEq:
case CompareLess:
case CompareLessEq:
@@ -1534,12 +1567,7 @@
return;
}
- if (node->op() == CompareEq && node->isBinaryUseKind(ObjectUse)) {
- def(PureValue(node));
- return;
- }
- if (node->child1().useKind() == UntypedUse || node->child1().useKind() == ObjectUse
- || node->child2().useKind() == UntypedUse || node->child2().useKind() == ObjectUse) {
+ if (node->isBinaryUseKind(UntypedUse)) {
read(World);
write(Heap);
return;
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2018-04-12 13:41:06 UTC (rev 230568)
@@ -761,6 +761,22 @@
break;
}
+ case PhantomNewObject:
+ case PhantomNewFunction:
+ case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncGeneratorFunction:
+ case PhantomNewAsyncFunction:
+ case PhantomCreateActivation:
+ case PhantomDirectArguments:
+ case PhantomClonedArguments:
+ case PhantomCreateRest:
+ case PhantomSpread:
+ case PhantomNewArrayWithSpread:
+ case PhantomNewArrayBuffer:
+ case BottomValue:
+ alreadyHandled = true;
+ break;
+
default:
break;
}
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2018-04-12 13:41:06 UTC (rev 230568)
@@ -685,9 +685,10 @@
}
case StringFromCharCode:
- if (node->child1()->shouldSpeculateInt32())
+ if (node->child1()->shouldSpeculateInt32()) {
fixEdge<Int32Use>(node->child1());
- else
+ node->clearFlags(NodeMustGenerate);
+ } else
fixEdge<UntypedUse>(node->child1());
break;
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGInPlaceAbstractState.h (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGInPlaceAbstractState.h 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGInPlaceAbstractState.h 2018-04-12 13:41:06 UTC (rev 230568)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,6 +27,7 @@
#if ENABLE(DFG_JIT)
+#include "DFGAbstractInterpreterClobberState.h"
#include "DFGAbstractValue.h"
#include "DFGBranchDirection.h"
#include "DFGFlowMap.h"
@@ -90,8 +91,13 @@
// you can safely call beginBasicBlock() on any basic block.
void reset();
+ AbstractInterpreterClobberState clobberState() const { return m_clobberState; }
+
+ // Would have the last executed node clobbered things had we not found a way to fold it?
+ bool didClobberOrFolded() const { return clobberState() != AbstractInterpreterClobberState::NotClobbered; }
+
// Did the last executed node clobber the world?
- bool didClobber() const { return m_didClobber; }
+ bool didClobber() const { return clobberState() == AbstractInterpreterClobberState::ClobberedStructures; }
// Are structures currently clobbered?
StructureClobberState structureClobberState() const { return m_structureClobberState; }
@@ -114,7 +120,8 @@
bool mergeToSuccessors(BasicBlock*);
// Methods intended to be called from AbstractInterpreter.
- void setDidClobber(bool didClobber) { m_didClobber = didClobber; }
+ void setClobberState(AbstractInterpreterClobberState state) { m_clobberState = state; }
+ void mergeClobberState(AbstractInterpreterClobberState state) { m_clobberState = mergeClobberStates(m_clobberState, state); }
void setStructureClobberState(StructureClobberState value) { m_structureClobberState = value; }
void setIsValid(bool isValid) { m_isValid = isValid; }
void setBranchDirection(BranchDirection branchDirection) { m_branchDirection = branchDirection; }
@@ -145,7 +152,7 @@
bool m_foundConstants;
bool m_isValid;
- bool m_didClobber;
+ AbstractInterpreterClobberState m_clobberState;
StructureClobberState m_structureClobberState;
BranchDirection m_branchDirection; // This is only set for blocks that end in Branch and that execute to completion (i.e. m_isValid == true).
Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGNodeType.h (230567 => 230568)
--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGNodeType.h 2018-04-12 13:41:00 UTC (rev 230567)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGNodeType.h 2018-04-12 13:41:06 UTC (rev 230568)
@@ -280,7 +280,7 @@
/* Optimizations for string access */ \
macro(StringCharCodeAt, NodeResultInt32) \
macro(StringCharAt, NodeResultJS) \
- macro(StringFromCharCode, NodeResultJS) \
+ macro(StringFromCharCode, NodeResultJS | NodeMustGenerate) \
\
/* Nodes for comparison operations. */\
macro(CompareLess, NodeResultBoolean | NodeMustGenerate) \