Title: [230568] branches/safari-605-branch
Revision
230568
Author
kocsen_ch...@apple.com
Date
2018-04-12 06:41:06 -0700 (Thu, 12 Apr 2018)

Log Message

Cherry-pick r230488. rdar://problem/39337455

    DFG AI and clobberize should agree with each other
    https://bugs.webkit.org/show_bug.cgi?id=184440

    Reviewed by Saam Barati.

    JSTests:

    Add tests for all of the bugs I fixed.

    * stress/direct-arguments-out-of-bounds-change-structure.js: Added.
    (foo):
    * stress/new-typed-array-cse-effects.js: Added.
    (foo):
    * stress/scoped-arguments-out-of-bounds-change-structure.js: Added.
    (foo.theO):
    (foo):
    * stress/string-from-char-code-change-structure-not-dead.js: Added.
    (foo):
    (i.valueOf):
    (weirdValue.valueOf):
    * stress/string-from-char-code-change-structure.js: Added.
    (foo):
    (i.valueOf):
    (weirdValue.valueOf):

    Source/_javascript_Core:

    One way to fix bugs involving underapproximation in AI or clobberize is to assert that they
    agree with each other. That's what this patch does: it adds an assertion that AI's structure
    state tracking must be equivalent to JSCell_structureID being clobbered.

    One subtlety is that AI sometimes folds away structure clobbering using information that
    clobberize doesn't have. So, we track this wuth special kinds of AI states (FoldedClobber and
    ObservedTransitions).

    This fixes a bunch of cases of AI missing clobberStructures/clobberWorld and one case of
    clobberize missing a write(Heap).

    This also makes some cases more precise in order to appease the assertion. Making things more
    precise might make things faster, but I didn't measure it because that wasn't the goal.

    * _javascript_Core.xcodeproj/project.pbxproj:
    * Sources.txt:
    * dfg/DFGAbstractInterpreter.h:
    * dfg/DFGAbstractInterpreterClobberState.cpp: Added.
    (WTF::printInternal):
    * dfg/DFGAbstractInterpreterClobberState.h: Added.
    (JSC::DFG::mergeClobberStates):
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::startExecuting):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::didFoldClobberWorld):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::clobberStructures):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::didFoldClobberStructures):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransition):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransitions):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::setDidClobber): Deleted.
    * dfg/DFGAtTailAbstractState.h:
    (JSC::DFG::AtTailAbstractState::setClobberState):
    (JSC::DFG::AtTailAbstractState::mergeClobberState):
    (JSC::DFG::AtTailAbstractState::setDidClobber): Deleted.
    * dfg/DFGCFAPhase.cpp:
    (JSC::DFG::CFAPhase::performBlockCFA):
    * dfg/DFGClobberSet.cpp:
    (JSC::DFG::writeSet):
    * dfg/DFGClobberSet.h:
    * dfg/DFGClobberize.h:
    (JSC::DFG::clobberize):
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants):
    * dfg/DFGInPlaceAbstractState.h:
    (JSC::DFG::InPlaceAbstractState::clobberState const):
    (JSC::DFG::InPlaceAbstractState::didClobberOrFolded const):
    (JSC::DFG::InPlaceAbstractState::didClobber const):
    (JSC::DFG::InPlaceAbstractState::setClobberState):
    (JSC::DFG::InPlaceAbstractState::mergeClobberState):
    (JSC::DFG::InPlaceAbstractState::setDidClobber): Deleted.

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

Modified Paths

Added Paths

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) \
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to