Title: [223679] branches/safari-604-branch
Revision
223679
Author
[email protected]
Date
2017-10-18 23:07:36 -0700 (Wed, 18 Oct 2017)

Log Message

Cherry-pick r221607. rdar://problem/35041474

Modified Paths

Added Paths

Diff

Modified: branches/safari-604-branch/JSTests/ChangeLog (223678 => 223679)


--- branches/safari-604-branch/JSTests/ChangeLog	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/JSTests/ChangeLog	2017-10-19 06:07:36 UTC (rev 223679)
@@ -1,5 +1,19 @@
 2017-10-18  Jason Marcell  <[email protected]>
 
+        Cherry-pick r221607. rdar://problem/35041474
+
+    2017-09-04  Saam Barati  <[email protected]>
+
+            typeCheckHoistingPhase may emit a CheckStructure on the empty value which leads to a dereference of zero on 64 bit platforms
+            https://bugs.webkit.org/show_bug.cgi?id=176317
+
+            Reviewed by Keith Miller.
+
+            * stress/dont-crash-when-hoist-check-structure-on-tdz.js: Added.
+            (Foo):
+
+2017-10-18  Jason Marcell  <[email protected]>
+
         Cherry-pick r223614. rdar://problem/34920288
 
     2017-10-18  Mark Lam  <[email protected]>

Added: branches/safari-604-branch/JSTests/stress/dont-crash-when-hoist-check-structure-on-tdz.js (0 => 223679)


--- branches/safari-604-branch/JSTests/stress/dont-crash-when-hoist-check-structure-on-tdz.js	                        (rev 0)
+++ branches/safari-604-branch/JSTests/stress/dont-crash-when-hoist-check-structure-on-tdz.js	2017-10-19 06:07:36 UTC (rev 223679)
@@ -0,0 +1,28 @@
+class Foo extends Object {
+    constructor(c1, c2) {
+        if (c1)
+            super();
+        let arrow = () => {
+            if (c2)
+                this.foo = 20;
+            else
+                this.foo = 40;
+        };
+        noInline(arrow);
+        arrow();
+    }
+}
+noInline(Foo);
+
+for (let i = 0; i < 1000; ++i)
+    new Foo(true, !!(i%2));
+
+let threw = false;
+try {
+    new Foo(false, true);
+} catch {
+    threw = true;
+} finally {
+    if (!threw)
+        throw new Error("Bad")
+}

Modified: branches/safari-604-branch/Source/_javascript_Core/ChangeLog (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/ChangeLog	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/ChangeLog	2017-10-19 06:07:36 UTC (rev 223679)
@@ -1,5 +1,67 @@
 2017-10-18  Jason Marcell  <[email protected]>
 
+        Cherry-pick r221607. rdar://problem/35041474
+
+    2017-09-04  Saam Barati  <[email protected]>
+
+            typeCheckHoistingPhase may emit a CheckStructure on the empty value which leads to a dereference of zero on 64 bit platforms
+            https://bugs.webkit.org/show_bug.cgi?id=176317
+
+            Reviewed by Keith Miller.
+
+            It turns out that TypeCheckHoistingPhase may hoist a CheckStructure up to
+            the SetLocal of a particular value where the value is the empty JSValue.
+            On 64-bit platforms, the empty value is zero. This means that the empty value
+            passes a cell check. This will lead to a crash when we dereference null to load
+            the value's structure. This patch teaches TypeCheckHoistingPhase to be conservative
+            in the structure checks it hoists. On 64-bit platforms, instead of emitting a
+            CheckStructure node, we now emit a CheckStructureOrEmpty node. This node allows
+            the empty value to flow through. If the value isn't empty, it'll perform the normal
+            structure check that CheckStructure performs. For now, we only emit CheckStructureOrEmpty
+            on 64-bit platforms since a cell check on 32-bit platforms does not allow the empty
+            value to flow through.
+
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+            * dfg/DFGArgumentsEliminationPhase.cpp:
+            * dfg/DFGClobberize.h:
+            (JSC::DFG::clobberize):
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::foldConstants):
+            * dfg/DFGDoesGC.cpp:
+            (JSC::DFG::doesGC):
+            * dfg/DFGFixupPhase.cpp:
+            (JSC::DFG::FixupPhase::fixupNode):
+            * dfg/DFGNode.h:
+            (JSC::DFG::Node::convertCheckStructureOrEmptyToCheckStructure):
+            (JSC::DFG::Node::hasStructureSet):
+            * dfg/DFGNodeType.h:
+            * dfg/DFGObjectAllocationSinkingPhase.cpp:
+            * dfg/DFGPredictionPropagationPhase.cpp:
+            * dfg/DFGSafeToExecute.h:
+            (JSC::DFG::SafeToExecuteEdge::SafeToExecuteEdge):
+            (JSC::DFG::SafeToExecuteEdge::operator()):
+            (JSC::DFG::SafeToExecuteEdge::maySeeEmptyChild):
+            (JSC::DFG::safeToExecute):
+            * dfg/DFGSpeculativeJIT.cpp:
+            (JSC::DFG::SpeculativeJIT::emitStructureCheck):
+            (JSC::DFG::SpeculativeJIT::compileCheckStructure):
+            * dfg/DFGSpeculativeJIT.h:
+            * dfg/DFGSpeculativeJIT32_64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGSpeculativeJIT64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGTypeCheckHoistingPhase.cpp:
+            (JSC::DFG::TypeCheckHoistingPhase::run):
+            * dfg/DFGValidate.cpp:
+            * ftl/FTLCapabilities.cpp:
+            (JSC::FTL::canCompile):
+            * ftl/FTLLowerDFGToB3.cpp:
+            (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+            (JSC::FTL::DFG::LowerDFGToB3::compileCheckStructureOrEmpty):
+
+2017-10-18  Jason Marcell  <[email protected]>
+
         Cherry-pick r223409. rdar://problem/34792148
 
     2017-10-16  JF Bastien  <[email protected]>

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2017-10-19 06:07:36 UTC (rev 223679)
@@ -2327,6 +2327,18 @@
         filter(value, set, admittedTypes);
         break;
     }
+
+    case CheckStructureOrEmpty: {
+        AbstractValue& value = forNode(node->child1());
+
+        bool mayBeEmpty = value.m_type & SpecEmpty;
+        if (!mayBeEmpty)
+            m_state.setFoundConstants(true);
+
+        SpeculatedType admittedTypes = mayBeEmpty ? SpecEmpty : SpecNone;
+        filter(value, node->structureSet(), admittedTypes);
+        break;
+    }
         
     case CheckStructureImmediate: {
         // FIXME: This currently can only reason about one structure at a time.

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -367,6 +367,7 @@
                     escapeBasedOnArrayMode(node->arrayMode(), node->child1(), node);
                     break;
 
+                case CheckStructureOrEmpty:
                 case CheckStructure: {
                     if (!m_candidates.contains(node->child1().node()))
                         break;
@@ -1091,6 +1092,7 @@
                     break;
                 }
 
+                case CheckStructureOrEmpty:
                 case CheckStructure:
                     if (!isEliminatedAllocation(node->child1().node()))
                         break;

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGClobberize.h (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGClobberize.h	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGClobberize.h	2017-10-19 06:07:36 UTC (rev 223679)
@@ -945,6 +945,7 @@
         return;
     }
         
+    case CheckStructureOrEmpty:
     case CheckStructure:
         read(JSCell_structureID);
         return;

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -139,7 +139,15 @@
                 // See: https://bugs.webkit.org/show_bug.cgi?id=174844
                 break;
             }
-                
+
+            case CheckStructureOrEmpty: {
+                const AbstractValue& value = m_state.forNode(node->child1());
+                if (value.m_type & SpecEmpty)
+                    break;
+                node->convertCheckStructureOrEmptyToCheckStructure();
+                changed = true;
+                FALLTHROUGH;
+            }
             case CheckStructure:
             case ArrayifyToStructure: {
                 AbstractValue& value = m_state.forNode(node->child1());

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGDoesGC.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -113,6 +113,8 @@
     case DeleteById:
     case DeleteByVal:
     case CheckStructure:
+    case CheckStructureOrEmpty:
+    case CheckStructureImmediate:
     case GetExecutable:
     case GetButterfly:
     case CheckSubClass:
@@ -254,7 +256,6 @@
     case GetMyArgumentByValOutOfBounds:
     case ForwardVarargs:
     case PutHint:
-    case CheckStructureImmediate:
     case PutStack:
     case KillStack:
     case GetStack:

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -1555,6 +1555,7 @@
         case GetVectorLength:
         case PutHint:
         case CheckStructureImmediate:
+        case CheckStructureOrEmpty:
         case MaterializeNewObject:
         case MaterializeCreateActivation:
         case PutStack:

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGNode.h (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGNode.h	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGNode.h	2017-10-19 06:07:36 UTC (rev 223679)
@@ -422,6 +422,12 @@
         m_opInfo = set;
     }
 
+    void convertCheckStructureOrEmptyToCheckStructure()
+    {
+        ASSERT(op() == CheckStructureOrEmpty);
+        setOpAndDefaultFlags(CheckStructure);
+    }
+
     void convertToCheckStructureImmediate(Node* structure)
     {
         ASSERT(op() == CheckStructure);
@@ -1623,6 +1629,7 @@
     {
         switch (op()) {
         case CheckStructure:
+        case CheckStructureOrEmpty:
         case CheckStructureImmediate:
         case MaterializeNewObject:
             return true;

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGNodeType.h (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGNodeType.h	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGNodeType.h	2017-10-19 06:07:36 UTC (rev 223679)
@@ -200,6 +200,7 @@
     macro(DeleteById, NodeResultBoolean | NodeMustGenerate) \
     macro(DeleteByVal, NodeResultBoolean | NodeMustGenerate) \
     macro(CheckStructure, NodeMustGenerate) \
+    macro(CheckStructureOrEmpty, NodeMustGenerate) \
     macro(GetExecutable, NodeResultJS) \
     macro(PutStructure, NodeMustGenerate) \
     macro(AllocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -886,6 +886,7 @@
                 m_heap.escape(node->child1().node());
             break;
 
+        case CheckStructureOrEmpty:
         case CheckStructure: {
             Allocation* allocation = m_heap.onlyLocalAllocation(node->child1().node());
             if (allocation && allocation->isObjectAllocation()) {

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -1053,6 +1053,7 @@
         case GetMyArgumentByValOutOfBounds:
         case PutHint:
         case CheckStructureImmediate:
+        case CheckStructureOrEmpty:
         case MaterializeNewObject:
         case MaterializeCreateActivation:
         case PutStack:
@@ -1065,8 +1066,7 @@
         case RecordRegExpCachedResult:
         case LazyJSConstant:
         case CallDOM: {
-            // This node should never be visible at this stage of compilation. It is
-            // inserted by fixup(), which follows this phase.
+            // This node should never be visible at this stage of compilation.
             DFG_CRASH(m_graph, m_currentNode, "Unexpected node during prediction propagation");
             break;
         }

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSafeToExecute.h (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2017-10-19 06:07:36 UTC (rev 223679)
@@ -36,12 +36,13 @@
 public:
     SafeToExecuteEdge(AbstractStateType& state)
         : m_state(state)
-        , m_result(true)
     {
     }
     
     void operator()(Node*, Edge edge)
     {
+        m_maySeeEmptyChild |= !!(m_state.forNode(edge).m_type & SpecEmpty);
+
         switch (edge.useKind()) {
         case UntypedUse:
         case Int32Use:
@@ -110,9 +111,11 @@
     }
     
     bool result() const { return m_result; }
+    bool maySeeEmptyChild() const { return m_maySeeEmptyChild; }
 private:
     AbstractStateType& m_state;
-    bool m_result;
+    bool m_result { true };
+    bool m_maySeeEmptyChild { false };
 };
 
 // Determines if it's safe to execute a node within the given abstract state. This may
@@ -134,6 +137,24 @@
     if (!safeToExecuteEdge.result())
         return false;
 
+    if (safeToExecuteEdge.maySeeEmptyChild()) {
+        // We conservatively assume if the empty value flows into a node,
+        // it might not be able to handle it (e.g, crash). In general, the bytecode generator
+        // emits code in such a way that most node types don't need to worry about the empty value
+        // because they will never see it. However, code motion has to consider the empty
+        // value so it does not insert/move nodes to a place where they will crash. E.g, the
+        // type check hoisting phase needs to insert CheckStructureOrEmpty instead of CheckStructure
+        // for hoisted structure checks because it can not guarantee that a particular local is not
+        // the empty value.
+        switch (node->op()) {
+        case CheckNotEmpty:
+        case CheckStructureOrEmpty:
+            break;
+        default:
+            return false;
+        }
+    }
+
     // NOTE: This tends to lie when it comes to effectful nodes, because it knows that they aren't going to
     // get hoisted anyway.
 
@@ -213,6 +234,7 @@
     case DefineDataProperty:
     case DefineAccessorProperty:
     case CheckStructure:
+    case CheckStructureOrEmpty:
     case GetExecutable:
     case GetButterfly:
     case CallDOMGetter:

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -7783,7 +7783,7 @@
     cellResult(resultGPR, node);
 }
 
-void SpeculativeJIT::compileCheckStructure(Node* node, GPRReg cellGPR, GPRReg tempGPR)
+void SpeculativeJIT::emitStructureCheck(Node* node, GPRReg cellGPR, GPRReg tempGPR)
 {
     ASSERT(node->structureSet().size());
     
@@ -7828,7 +7828,7 @@
     case CellUse:
     case KnownCellUse: {
         SpeculateCellOperand cell(this, node->child1());
-        compileCheckStructure(node, cell.gpr(), InvalidGPRReg);
+        emitStructureCheck(node, cell.gpr(), InvalidGPRReg);
         noResult(node);
         return;
     }
@@ -7846,7 +7846,7 @@
             m_jit.branchIfNotOther(valueRegs, tempGPR));
         JITCompiler::Jump done = m_jit.jump();
         cell.link(&m_jit);
-        compileCheckStructure(node, valueRegs.payloadGPR(), tempGPR);
+        emitStructureCheck(node, valueRegs.payloadGPR(), tempGPR);
         done.link(&m_jit);
         noResult(node);
         return;

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2017-10-19 06:07:36 UTC (rev 223679)
@@ -2850,8 +2850,8 @@
     void compileIsObjectOrNull(Node*);
     void compileIsFunction(Node*);
     void compileTypeOf(Node*);
-    void compileCheckStructure(Node*, GPRReg cellGPR, GPRReg tempGPR);
     void compileCheckStructure(Node*);
+    void emitStructureCheck(Node*, GPRReg cellGPR, GPRReg tempGPR);
     void compilePutAccessorById(Node*);
     void compilePutGetterSetterById(Node*);
     void compilePutAccessorByVal(Node*);

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -5631,6 +5631,10 @@
         unreachable(node);
         break;
 
+    case CheckStructureOrEmpty:
+        DFG_CRASH(m_jit.graph(), node, "CheckStructureOrEmpty only used in 64-bit DFG");
+        break;
+
     case LastNodeType:
     case Phi:
     case Upsilon:

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -4620,6 +4620,22 @@
         break;
     }
         
+    case CheckStructureOrEmpty: {
+        SpeculateCellOperand cell(this, node->child1());
+        GPRReg cellGPR = cell.gpr();
+        MacroAssembler::Jump isEmpty;
+        if (m_interpreter.forNode(node->child1()).m_type & SpecEmpty)
+            isEmpty = m_jit.branchTest64(MacroAssembler::Zero, cellGPR);
+
+        emitStructureCheck(node, cellGPR, InvalidGPRReg);
+
+        if (isEmpty.isSet())
+            isEmpty.link(&m_jit);
+
+        noResult(node);
+        break;
+    }
+
     case CheckStructure: {
         compileCheckStructure(node);
         break;

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGTypeCheckHoistingPhase.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGTypeCheckHoistingPhase.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGTypeCheckHoistingPhase.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -177,8 +177,14 @@
                     Edge child1 = node->child1();
                     
                     if (iter->value.m_structure) {
+                        // Note: On 64-bit platforms, cell checks allow the empty value to flow through.
+                        // This means that this structure check may see the empty value as input. We need
+                        // to emit a node that explicitly handles the empty value. Most of the time, CheckStructureOrEmpty
+                        // will be folded to CheckStructure because AI proves that the incoming value is
+                        // definitely not empty.
+                        static_assert(is64Bit() || !(SpecCellCheck & SpecEmpty), "");
                         insertionSet.insertNode(
-                            indexForChecks, SpecNone, CheckStructure,
+                            indexForChecks, SpecNone, is64Bit() ? CheckStructureOrEmpty : CheckStructure,
                             originForChecks.withSemantic(origin.semantic),
                             OpInfo(m_graph.addStructureSet(iter->value.m_structure)),
                             Edge(child1.node(), CellUse));

Modified: branches/safari-604-branch/Source/_javascript_Core/dfg/DFGValidate.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/dfg/DFGValidate.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/dfg/DFGValidate.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -269,6 +269,11 @@
                     VALIDATE((node), !!node->child1());
                     VALIDATE((node), !!node->cellOperand()->value() && node->cellOperand()->value().isCell());
                     break;
+                case CheckStructureOrEmpty:
+                    VALIDATE((node), is64Bit());
+                    VALIDATE((node), !!node->child1());
+                    VALIDATE((node), node->child1().useKind() == CellUse);
+                    break;
                 case CheckStructure:
                 case StringFromCharCode:
                     VALIDATE((node), !!node->child1());

Modified: branches/safari-604-branch/Source/_javascript_Core/ftl/FTLCapabilities.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -65,6 +65,7 @@
     case BitLShift:
     case BitURShift:
     case CheckStructure:
+    case CheckStructureOrEmpty:
     case DoubleAsInt32:
     case ArrayifyToStructure:
     case PutStructure:

Modified: branches/safari-604-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (223678 => 223679)


--- branches/safari-604-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-10-19 05:44:33 UTC (rev 223678)
+++ branches/safari-604-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-10-19 06:07:36 UTC (rev 223679)
@@ -606,6 +606,9 @@
         case CheckStructure:
             compileCheckStructure();
             break;
+        case CheckStructureOrEmpty:
+            compileCheckStructureOrEmpty();
+            break;
         case CheckCell:
             compileCheckCell();
             break;
@@ -2705,6 +2708,39 @@
             return;
         }
     }
+
+    void compileCheckStructureOrEmpty()
+    {
+        ExitKind exitKind;
+        if (m_node->child1()->hasConstant())
+            exitKind = BadConstantCache;
+        else
+            exitKind = BadCache;
+
+        LValue cell = lowCell(m_node->child1());
+        bool maySeeEmptyValue = m_interpreter.forNode(m_node->child1()).m_type & SpecEmpty;
+        LBasicBlock notEmpty;
+        LBasicBlock continuation;
+        LBasicBlock lastNext;
+        if (maySeeEmptyValue) {
+            notEmpty = m_out.newBlock();
+            continuation = m_out.newBlock();
+            m_out.branch(m_out.isZero64(cell), unsure(continuation), unsure(notEmpty));
+            lastNext = m_out.appendTo(notEmpty, continuation);
+        }
+
+        checkStructure(
+            m_out.load32(cell, m_heaps.JSCell_structureID), jsValueValue(cell),
+            exitKind, m_node->structureSet(),
+            [&] (RegisteredStructure structure) {
+                return weakStructureID(structure);
+            });
+
+        if (maySeeEmptyValue) {
+            m_out.jump(continuation);
+            m_out.appendTo(continuation, lastNext);
+        }
+    }
     
     void compileCheckCell()
     {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to